Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$location.path not working from http interceptor

Tags:

angularjs

this is your fairly straight-forward setup, I have an http interceptor that's looking for 401s, if found the user is redirected to the login page:

function($location, $q)
{
    return {
        request: function (config) {
            return config || $q.when(config);
        },
        requestError: function(request){
            return $q.reject(request);
        },
        response: function (response) {
            return response || $q.when(response);
        },
        responseError: function (response)
        {
            if (response && response.status === 401)
            {
                $location.path('/login');                    
            }

            return $q.reject(response);
        }
    };

}

The problem is the $location.path('/login') call doesn't seem to work, the path is completely disregarded and I remain on the route (albeit a blank page) I was on when my session expires. One possible workaround is to use the traditional window.location = '/#!/login'; but I find this to be less than ideal. I also find that if I remove the return $q.reject(response); line I get it working, BUT this introduces another error where the response's data property cannot be found (solution discussed here: Angular.js $http.post TypeError: Cannot read property 'data' of undefined).

I am running angular 1.2.21.

Any ideas on what might be going on here? Reverting to window.location isn't the end of the world but I'd love a nice tidy solution to this mystery :).

Thanks in advance.

like image 911
wittyhandle Avatar asked Aug 30 '14 07:08

wittyhandle


1 Answers

I have the same problem.

I'm not sure but looks like $location.path(...) does not change location because app waits until all promises will be resolved, and the promise inside the interceptor is rejected (return $q.reject(response);)

In my case the service that does http request is placed inside the resolve section of UI-router state, so I can use $stateChangeError event to handle the error. (for ngRoute use $routeChangeError event)

Hope this can help you :)

NB The backend of my app return custom error messages in 401 response body

PS There must be some better solution

UPDATE:

More universal workaround:

interceptor inside the module.config

...
responseError: function (response) {
    if (response && response.status === 401) {
        $rootScope.$emit('loginRequired');
    }

    return $q.reject(response);
}
...

and event handler somewhere in module.run section

$rootScope.$on('loginRequired', function() {
    $location.path('/login');
});

(I've tested handler with $state.go('login') but $location.path('/login'); should works too :) )

like image 177
Sirozha Avatar answered Oct 19 '22 23:10

Sirozha