S3 web hosting for backbone.js application with pushState - javascript

I'm hosting a Backbone application on Amazon S3 using a custom domain name. The Backbone application router handles all routes under the root ('/'). I would like to use pushState, so there's no need for the # prefix on my application routes.
Basically, i want all sub-routes to be routed by S3 to the domain root and let Backbone do the rest.
I added the following rule:
<RoutingRules>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals >
</Condition>
<Redirect>
<HostName>mydomain.com</HostName>
<ReplaceKeyPrefixWith>#</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
</RoutingRules>
But this just adds the # sign prefix to all my sub-routes. I want to avoid that.
How do I set the redirection rules on my S3 bucket to route everything to the indexed document without having to add the #?

Use bucket URL instead of your domain URL:
<HostName>BUCKET_NAME.s3-website-ap-northeast-1.amazonaws.com</HostName>
Also check you anchor links dont have # in url Home instead have links like this:
Home
About
Then using jQuery you can navigate the link to router
$(document).on('click', 'a[href^="/"]', function (e) {
e.preventDefault();
var href = $(e.currentTarget).attr('href');
Backbone.history.navigate(href, { trigger: true });
});

Related

How Can I do the dynamic redirects in nextjs

I currently have a Next.js application which have dynamic routing. I have URLs of this form /o/:organizationIdentifier*/p/:projectIdentifier*/e/:environmentIdentifier*/settings/notification/categories
I want to create a documentation which won't need to specify the organizationIdentifier, projectIdentifier or environmentIdentifier. A user will just click on a link like, /settings/notification/categories and it will redirect them to the /o/:organizationIdentifier*/p/:projectIdentifier*/e/:environmentIdentifier*/settings/notification/categories and these variables will be pulled from a redux store. However, I tried something like:
const rewrites = [
{
source: "/settings/notification/categories",
destination: "/o/:organizationIdentifier*/p/:projectIdentifier*/e/:environmentIdentifier*/settings/notification/categories",
"permanent":true,
"locale":false
}
]
but I keep getting errors:
destination has segments not in source or has
(organizationIdentifier, projectIdentifier, environmentIdentifier) for
route
{"source":"/settings/notification/categories","destination":"/o/:organizationIdentifier*/p/:projectIdentifier*/e/:environmentIdentifier*/settings/notification/categories","permanent":true,"locale":false}`
and
Error: Invalid redirects found
Any help on how I can achieve this functionality?

How to redirect users to a subdomain based on IP location?

I am using Node Express for my website and I would like to redirect users based on their current location, for example, if users in Singapore open site.com, then redirect them to the subdomain sg.site.com (this one is hosted on the same server as site.com). I am able to find user's IP address and location but how to redirect them to the proper subdomain?
If you mean from server-side Express code, with res.redirect:
res.redirect([status,] path)
Redirects to the URL derived from the specified path, with specified status, a positive integer that corresponds to an HTTP status code . If not specified, status defaults to “302 “Found”.
res.redirect('/foo/bar');
res.redirect('http://example.com');
res.redirect(301, 'http://example.com');
res.redirect('../login');
If you mean client-side, assign to the location object.
Replace the current document with the one at the given URL:
function goMoz() {
window.location = "http://www.mozilla.org";
}
You can do
res.redirect('https://app.example.io');
Express docs: https://expressjs.com/en/api.html#res.redirect
It works basically like you would redirect users to an external page,but you can add your subdomain as well. Like this one:
function requestHandler(req, res) {
res.redirect('https://sg.site.com');
}

Marionette app 2 way navigation with history api

I have node.js server application (rest API service).
I also have Backbone + Marionette(for my serverside RESTful app) multiple page app at the client side.
I currently have Marionette navigation which is work pretty good with links like domain.com/#feedbacks (pages are render on client side with ajax data). But I also want to add serverside navigation e.g. domain.com/feedbacks (for google and other seach engines).
The question is: How can I match serverside and clientside navigations?
Mb I should try to add event handler for all links on page, which is will do something like Backbone.history.navigate("/feedbacks")? But I have a lot different hash links(#feedbacks)... Mb there is a more elegant solution? Thank you.
My current marionette router:
var AppRouter = Backbone.Blazer.Router.extend({
routes: {
'': new HomeRoute(),
'sell': new SellRoute(),
'login': new LoginRoute(),
'feedbacks': new FeedbacksRouter(),
'product/:id': new ProductRoute(),
'profile/:id': new UserRoute()
}
})
I just had to use:
Backbone.history.start({pushState: true})
instead of:
Backbone.history.start();
It make backbone routing work without # symbols

Backbone Routing with Static HTML files

I'm working on a website where we are using 3rd Party web services to return dynamic content and using javascript to parse and display that data from to the page. We are already using backbone in a couple places on the site to post data to web services so I had the thought of trying to use Backbone's router to run specific functions based on the page url and grabbing the query because we are hashing the queries to the url of the page.
For example: global-site-search.html#query
This is the router code I have to this point:
var Router = Backbone.Router.extend({
routes : {
'' : 'indexRoute',
'global-site-search.html(:query)' : 'getSearchResults'
},
indexRoute: function(query) {
console.log("indexRoute");
},
getSearchResults: function(query) {
console.log("getSearchResults with query", query);
}
});
var WaRouter = new Router();
Backbone.history.start({
pushState: true,
root: '/'
});
But when I hit the page with a url like global-site-search.html#query the query value returns null. Has anyone tried this before or am I trying to extend Backbone's router to far in handling this?
Is global-site-search.html from your server?, if yes then the config for router should be
':query' : 'getSearchResults'
If no, then you can't do that, because Backbone.Router uses the hash part of the current page URL to track pages. And since global-site-search.html is not containing any backbone code, it can't do anything. It is possible only if you somehow can inject your router code into global-site-search.html which is illegal in this case
Updated: this should allow you to search with this route ':query' : 'getSearchResults'
Backbone.history.start({
pushState: true,
root: window.location.pathname
});
When using router, you need to set the correct root, so using window.location.pathname is the easiest way to do that. Also, according to Backbone documentation
and if a hash URL is visited by a pushState-capable browser, it will be transparently upgraded to the true URL. Note that using real URLs requires your web server to be able to correctly render those pages, so back-end changes are required as well. For example, if you have a route of /documents/100`
Since you are not having any real back-end to handle pushState, I suggest that you turn it off

How do I generate a unique link that will load a session with certain docs available to the client?

Sorry for the bad phrasing.
Essentially, I want to be able to generate a link to a page, which will load a session of certain docs.
For example, Links.find() returns to Client A Links.find({clientName:"A"}). Now Client A wants to send this series of elements to his friend, and wants to do so by sending him a link which loads a client instance that can see Links.find({clientName"A"}).
Any input at all would be greatly appreciated.
Add Iron Router to your project. Then create a route that puts the relevant query into the URL, for example (in a client-loaded JavaScript file):
Router.map(function () {
this.route('client', {
path: '/client/:_clientName',
before: function () {
this.subscribe('client', this.params._clientName).wait();
}
}
}
Then a URI like http://yourapp.com/client/A would cause the client template to render (by default it uses the same name as the route name, unless you specify a different name) subscribing to the client subscription using "A" as the subscription parameter. This would be paired on the server side with:
Meteor.publish('client', function (clientName) {
// Clients is a Meteor collection
return Clients.find({clientName: clientName});
});
So that's how to process links after they've been generated. As for creating them, just work backwards: what query parameters are you passing to your subscription (that in turn get put into the find() call to MongoDB)? Identify each of them and write some code that adds them to an appropriate URI—in this case, your function would simply concatenate "http://yourapp.com/client/" with clientName, in this case "A". Obviously much-more-complicated routes/URIs and queries are possible, for example http://yourapp.com/events/2012-01-01/2012-12-31 with an Iron Router route path of /events/:_fromDate/:_toDate and so on.

Categories