Ember.JS: How to handle invalid URLs

There’s a lot of documentation for the new Ember Router. However, I found that no one was talking about how to handle the “*” route in Ember, i.e. the routes that don’t match anything.

I first tried to look at the ApplicationRoute but that didn’t seem to throw anything. Ember just sits there with a lovely blank page!

 

ApplicationRoute { 
events: {
errors: function(reason, transition) {
console.log("never happened");
}
}
}

So here’s the easiest solution for handling bad urls. My router looks like this now:

App.Router.map( function() {

this.route('login');
this.resource('companies', {path: 'companies'});
this.resource('company', {path: 'companies/:company_nice_url'}, function() {
this.route('members');

});



this.route('bad_url', { path: '/*badurl' }); // Catch everything else!

});

The last route named “bad_url” will catch all the other unrecognized URLs and direct the user to the App.BadUrlRoute where you can handle them. You will get the URL segment as params.bad_url for you to inspect and offer friendly advice like “hey did you mistype companies?”.

If you simply want to show a page that says “There’s no one here you fool!”, just create a handlebars template:

<script type="text/x-handlebars" data-template-name="bad-url">
<h1>There’s no one here you fool!!!!</h1>
</script>

And you’re done! Any path that doesn’t match your routes will get routed through ‘bad-url’, where you can act on it accordingly.

 

EDIT ON 6TH AUGUST

Marcus in the comments pointed out to me that using path: '/*badurl'  is better due to this handling "/this/is/wrong/path" situations. My initial solution to using a dynamic segment (:bad_url) did not catch this. Thanks to all the commenters!

 

EDIT ON 7TH AUGUST

I have realised that having "*badurl" instead of ":bad_url" has one caveat. I am implementing a funky search route that deals with all URLs past a base route like this: /search/x/y/z/a/b/c . Having the astriks to catch all the bad url's makes it impossible to have a search router which deals with "/search/*search_terms". So there you go... ups and downs to both methods. More on that awesome search route another day... :)

 

Passing session keys in headers for Embjer.JS Data REST calls

First thing you have to do is to override the RESTAdapter if you aren't already. The ajax function is the key. It is given the jQuery hash that will get passed down so all you have to do is to populate the beforeSend key with a function like below. The 'xhr' passed in can be set with a request header value.

DS.MyAppRESTAdapter = DS.RESTAdapter.extend({

ajax: function(url, type, hash) {

hash.beforeSend = function (xhr) {
if (MyApp.isLoggedIn()) {
xhr.setRequestHeader('x-token', MyApp.session.token);
}
};

// handle errors if ember-data doesn't already
if (hash.error == undefined) {
hash.error = function(xhr) {
this.didError(null, type, null, xhr);
}
}
// do some other work and call super()
...
this._super(url, type, hash);
},

didError: function(store, type, record, xhr) {
if (xhr.status == 401) { ... }
}
});

That's it! Your app should now be firing off request headers like a pro! I've also left my basic error handling code to catch instances when ember-data simply does nothing. This will probably change in the future leading up to a stable 1.0.

Still learning this stuff, happy to hear about a better way to do it if you know :).