在 Angular 请求拦截器上获取上一个 URL

Get previous URL on Angular request interceptor

我正在实施 angular 页面范围 authentication app

它是一个使用拦截器的事件机器,所以如果任何请求导致 401 响应,它会弹出一个登录模式。登录成功后,它会再次执行请求(如果登录用户没有足够的权限访问所请求的资源,这也可能导致 403)。

这么久,除了当用户取消登录过程时,一切都按预期工作,$location.path() 仍然指向请求的资源。我想将其恢复到以前的路径。所以:

如我所料

我希望能够像这样得到“被叫方”URL:

.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);
    },

我希望这一行给我“被调用者”路径,但它实际上给了我请求的路径(angular 在执行请求之前已经更改了它)。

路线提供商

.config(['$routeProvider', function($routeProvider) {
  $routeProvider
  .when('/admin', {
    templateUrl: "/admin"
  })
  .otherwise({ redirectTo: '/' });
}])

这个顽皮的小男孩在请求之前改变了我的路径。我想我可以在这里做一些关于 resolve 的事情,但我觉得这没有用,因为它会完全破坏封装,迫使我每次调用任何受保护的资源时都要 resolve,所以我可以将当​​前路径传递给我的某些服务授权应用

那么,如何从拦截器或 auth 应用程序中的某些服务中获取先前的路径,而不是从路由提供程序配置中明确发送它?

你为什么不观察 $on 路由更改事件并将你的 current/previous 路径绑定到 $window 或全局 $scope 变量?

我还没有阅读你上面的所有代码,但这是我在我的应用程序中处理位置 事物 的方式:

$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;
});

它是如何工作的:

1.获取当前和以前的 url:

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

...如果您的路由定义为 /admin/:userID 并且您在该页面上,url 将包含该特定用户 ID,它不会 return 参数名称. /admin/53 将是 /admin/53.

2。从当前 url:

中获取特定的 url 片段
$scope.uriSegment[1]

... 对于当前 url 像 /admin/53 将打印 53

上面的代码中还有很多东西,但我认为这就是你需要的——记住前面的url。您可以玩转路线事件并构建您自己的路线事件。
我看到你在你的工厂中注入了 $routeScope,所以你可以在你的主控制器中添加我的代码,并在每次路由更改时将 $routeScope 更新为 routeData 然后你可以这样做:

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

关于路线事件的更多信息here