angularjs - Infinite loop in interceptor -
i've made angularjs website working api. api provides few features authentication (oauth).
when api returns 401 error, means access_token
has expired , needs refreshed refresh_token
.
i created interceptor in angularjs. goal check if result returned api 401 error , if it's case, must refresh token , then, process previous rejected request.
the problem interceptor creates infinite loop. after second failure of initial request, should stop doesn't.
angular.module('myapp') .factory('authinterceptor', function ($rootscope, $q, $window, $injector) { return { // if api returns error 'responseerror' : function(rejection) { // if it's 401 if (rejection.status == 401) { var deferred = $q.defer(); $injector.get('$http').post('http://my-api.local/api/oauth/token', { grant_type : 'refresh_token', client_id : 'id', client_secret : 'secret', refresh_token : $window.sessionstorage.refresh_token }, { headers : { 'content-type' : 'application/x-www-form-urlencoded' }, transformrequest : function(obj) { var str = []; for(var p in obj) str.push(encodeuricomponent(p) + "=" + encodeuricomponent(obj[p])); return str.join("&"); } }) // new token request successfull .success(function(refreshresponse) { // processing failed request again (should fail again because didn't saved new tokens) $injector.get('$http')(rejection.config).success(function(data) { deferred.resolve(data); }) .error(function(error, status) { deferred.reject(); }); return deferred.promise(); }) // new token request failure .error(function(error, status) { deferred.reject(); // $location.path('users/login'); return; }); } // if it's errorenter code here else return rejection; } } });
so code:
- starts when first request fails
- refreshes token
- retries request fails again (<- want make stop here)
- refreshes token
- retries request fails again
- refreshes token
- retries request fails again
- etc...
i worked on in app. refresh request needs include config/header variable skipintercept: true
. when intercept failed response, can check rejection.config.skipintercept
variable. if true, go straight $q.reject(rejection)
.
where have:
if (rejection.status == 401) {
change to:
if (rejection.status == 401 && !rejection.config.skipintercept) {
and above this:
headers : { 'content-type' : 'application/x-www-form-urlencoded' },
you need add:
skipintercept: true, headers: { 'content-type' : 'application/x-www-form-urlencoded' },
ps. there's existing solution can use.
Comments
Post a Comment