当前位置: 动力学知识库 > 问答 > 编程问答 >

angularjs - Get previous URL on Angular request interceptor

问题描述:

I'm implementing an angular page-wide authentication app.

It is an event machine that uses an interceptor, so if any request results in a 401 response, it pops a login modal. When the login succeeds, it performs the request again (which could as well result in a 403 if the logged user do not have enough privileges to access the requested resource).

So long, things are working as expected except that when the user cancels the login process, the $location.path() still points to the requested resource. I want to revert this to the previous path. So:

What I expected

I expected to be able to get the "callee" URL like so:

.factory('authInterceptor', ...

return {

// Append the authentication headers to every request

request: function(config) {

previousLocation = $location.path(); // <--- HERE

if(Session.exist) {

config.headers.Authorization = Session.token;

}

return config || $q.when(config);

},

I expected this line to give me the "callee" path, but it actually gives me the requested one (angular has changed it before performing the request).

The route provider

.config(['$routeProvider', function($routeProvider) {

$routeProvider

.when('/admin', {

templateUrl: "/admin"

})

.otherwise({ redirectTo: '/' });

}])

This naughty little boy is changing my path prior to the request. I guess I can do something here on resolve, but I don't find this useful, since it will completely break encapsulation, forcing me to resolve each time I call any protected resource, so I can pass the current path to some service in my auth app.

So, how can I get the previous path from the interceptor, or some service within the auth app, without explicitly sending it from the route provider configuration?

网友答案:

Why don't you watch $on route change events and bind your current/previous paths to a $window or global $scope variable?

I haven't read all your code above, but this is how I handle location things within my app:

$scope.$on('$routeChangeSuccess', function(evt, current, previous){
    var routeData = {};

    //prop: uriSegment
    //desc: get all uri segments for current location
    routeData.uriSegment = [];
    routeData.uriSegment = $location.path().substr(1).split('/');

    //prop: urls
    //desc: get current & previous urls
    routeData.urls = {};
    routeData.urls.curr = $location.url().substr(1);
    //...previous url
    if(previous && previous.originalPath){
        //remove matching structure & slashes from url & add params as plain values
        var prevUrl = previous.originalPath.substr(1).replace('/:', '/').replace(':', '');
        if(previous.pathParams){
            angular.forEach(previous.pathParams, function(val, key){
                prevUrl = prevUrl.replace(key, val);
            });
        }
        routeData.urls.prev = prevUrl;
    }


    //bind routeData to scope/window...
    $scope.uriSegment = routeData.uriSegment;
    $scope.urls = routeData.urls;
});

How does it work:

1. Get current & previous url:

$scope.urls.curr //shows current url
$scope.urls.prev //shows previous url

... if your route is defined like /admin/:userID and you are on that page, the url will contain that specific userID, it won't return the param name. /admin/53 will be /admin/53.

2. Get a specific url segment from current url:

$scope.uriSegment[1]

... for current url like /admin/53 will print 53

There were a lot more things in the above code, but I think that's what you need - to remember the previous url. You can play with route events and build your own.
I see that you inject $routeScope in your factories, so you can add my code in your main controller and update the $routeScope with routeData on every route change and then you can go like this:

...
previousLocation = $rootScope.urls.prev;
...

More about route events here.

分享给朋友:
您可能感兴趣的文章:
随机阅读: