HTTP error handling


#1

Hi,

I’m currently working on an ember app using ember-data for the communication with the back-end (Rails-API). At the moment my API returns HTTP status code 403 (forbidden), if a user tries to access a resource without permission. For some days I searched the web, how HTTP errors could be handled globally on my ember app. I only found how to handle these kind of errors on route changes (model, beforeModel, afterModel), but I didn’t find anything usable for save, so I started to look at the ember-data code, that is responsible for validation and http errors. The only way I could find at the moment, is to catch the error on save, and do some custom error handling for every models save, like this:

actions:
  saveModel: (model) ->
    model.save().catch((reason) ->
      # error handling, show error message, route transition, ...

But for my usecase and I think also for usecases of others, it would be nicer to have the errors bubble up like they do on route changes, such that you can use:

actions:
  errors: (error) ->
    # error handling or bubble up to parent route and so on.

With such a solution it would be very easy to have specific error handling or a global error handle for authorization and other global stuff.

So I ask myself, how do others implement the server side error handling in there ember apps?


#2

Well, I think it depends. With Ember Data I’d do.

jQuery(document).ajaxError (e, xhr, options, thrownError) ->
 #  do some error handling here.

I think the http status is saved in the xhr.


#3

Yes, that should work, but it feels a bit like working against the framework. I think, if I use a persistence framework and there occure errors on save/update, then the framework should give me a way to handle this errors directly, without bypassing them to jQuery. After looking at the code for the error handling, I think it’s a problem, that’s hard to solve. Because at the moment the error handling goes from adapter to store and then the store informs the model, but I think not all errors should be handled by the model (maybe only validation ones).

Anyway, thanks for you suggestion, I think I will use it as workaround at the moment.


#4

@kunerd did you find a better solution? I have exactly the same problem and I don’t know which approach is the better. At the moment I am doing that in my application but I would like it to be like I have it in the comments: https://gist.github.com/vasilakisfil/f3380e4ff5fd6860bb15

Did you find something better ?


#5

For validation errors, @alexspeller wrote a great article on how to get errors sent to DS.Errors on your model.

As for handling the 401 statusCode, I’ve done some instrumentation/eventing between my adapter and anything that wants to listen for XHR errors (usually just my application router).


#6

@vasilakisfil: Last time I worked on my application I used this:

HTTPErrorsInitializer = 
  name: 'http-errors'
  initialize: (container) ->
     Ember.$(document).ajaxError (e, xhr, options, thrownError) ->
        container.lookup('router:main').send('httpError', e, xhr, options, thrownError)

Sorry for the Coffeescript. It creates an event for every ajaxError, which bubbles up along the routes and controllers. You could handle that event in a specific route/controller or for the general cases in the application router/controller.


#7

thanks @kunerd, it’s neat!


#8

FYI ajaxError is deprecated.

One technique you could use is to make an API Service. Which you can use to make rest and non-rest calls (essentially just a wrapper for icajax). This can then catch and normalise all your failed responses e.g 403 -> ForbiddenError.

Then, you can make your adapter utilise the API Service rather than using its own ajax method.

This means you can do:

this.apiService.ajax(...) or
this.store.findRecord(...)

and all errors will be handled in the same way.