$location.path not working from http interceptor
Asked Answered
C

1

6

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.

Cordelia answered 30/8, 2014 at 7:10 Comment(1)
Related question: #19499823Ium
I
2

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 :) )

Ium answered 8/12, 2014 at 22:14 Comment(2)
The similar soulution: blog.brunoscopelliti.com/… (the difference is that the .success() callback is used)Ium
My code work with $state.go('login') but $location.path is not workTullius

© 2022 - 2024 — McMap. All rights reserved.