emberjs handle 401 not authorized

允我心安 提交于 2019-11-30 05:19:08

AFAIK this is not addressed by the current implementation of ember-data and the ember-data README states that "Handle error states" is on the Roadmap.

For the time being, you can implement your own error handling adapter. Take a look at the implementation of the DS.RestAdapter . By using that as a starter, it should not be too difficult to add error handling in there (e.g simply add an error function to the the data hash that is passed to the jQuery.ajax call).

As of the current version of Ember Data (1.0 beta) you can override the ajaxError method of DS.RESTAdapter:

App.ApplicationAdapter = DS.RESTAdapter.extend({
  ajaxError: function(jqXHR) {
    var error = this._super(jqXHR);
    if (jqXHR && jqXHR.status === 401) {
      #handle the 401 error
    }
    return error;
  }
});

Note that you should call @_super, especially if you are overriding one of the more complex adapters like DS.ActiveModelAdapter, which handles 422 Unprocessable Entity.

For those willing to accept a solution that does lose changes and state you can register a jQuery ajaxError handler to redirect to a login page.

$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {
  // You should include additional conditions to the if statement so that this
  // only triggers when you're absolutely certain it should
  if (jqXHR.status === 401) {
    document.location.href = '/users/sign_in';
  }
});

This code will get triggered anytime any jQuery ajax request completes with an error.

Of course you would never actually use such a solution as it creates an incredibly poor user experience. The user is yanked away from what they're doing and they lose all state. What you'd really do is render a LoginView, probably inside of a modal.

An additional nicety of this solution is that it works even if you occasionally make requests to your server outside of ember-data. The danger is if jQuery is being used to load data from other sources or if you already have some 401 error handling built-in elsewhere. You'll want to add appropriate conditions to the if statement above to ensure things are triggered only when you're absolutely certain they should.

It's not addressed by ember-data (and probably won't be), but you can reopen the DS class and extend the ajax method.

It looks like this:

ajax: function(url, type, hash) {
  hash.url = url;
  hash.type = type;
  hash.dataType = 'json';
  hash.contentType = 'application/json; charset=utf-8';
  hash.context = this;

  if (hash.data && type !== 'GET') {
    hash.data = JSON.stringify(hash.data);
  } 

  jQuery.ajax(hash);
},

You can rewrite it with something like this (disclaimer: untested, probably won't work):

DS.reopen({
    ajax: function(url, type, hash) {
        var originalError = hash.error;
        hash.error = function(xhr) {
            if (xhr.status == 401) {
                var payload = JSON.parse(xhr.responseText);
                //Check for your API's errorCode, if applicable, or just remove this conditional entirely
                if (payload.errorCode === 'USER_LOGIN_REQUIRED') {
                    //Show your login modal here
                    App.YourModal.create({
                        //Your modal's callback will process the original call
                        callback: function() {
                            hash.error = originalError;
                            DS.ajax(url, type, hash);
                        }
                    }).show();
                    return;
                }
            }
            originalError.call(hash.context, xhr);
        };
        //Let ember-data's ajax method handle the call
        this._super(url, type, hash);
    }
});

What we're doing here is essentially deferring the call that received the 401 and are preserving the request to be called again when login is complete. The modal's ajax call with have the original error applied to it from the original ajax call's hash, so the original error would still work as long as it's defined :-)

This is a modified implementation of something we're using with our own data-persistence library, so your implementation might vary a bit, but the same concept should work for ember-data.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!