3

Angular http拦截器不适用于从拦截器内初始化的请求?

在我们的代码库中,对我们 api 的每个请求都有一个以 url 开头的 url,/api/并且我们有一个拦截器,它使用我们 api 的实际地址更新这些请求(使得在开发和生产环境之间轻松切换一件事)。更新 url 后,如果存在访问令牌,拦截器还会添加 Authorization 标头。这一切都完美无缺。

但是,有时访问令牌已过期,但我们仍然有一个刷新令牌,在继续实际请求之前,我首先想向我们的 api 发出请求以获取新的访问令牌。

因此,在request我们的拦截器部分,我们调用了一个负责刷新访问令牌的服务,并且在该then方法返回的回调中,我们更新了原始请求的配置:

//This interceptor only applies to our api calls, do nothing for other requests
if(config.url.substring(0, API_PREFIX.length) !== API_PREFIX) {
    return config;
}

config.url = config.url.replace(API_PREFIX, API_ENDPOINT);

// if we are authenticated, we add the authorization header already
if(AuthSessionService.isAuthenticated()) {
    config.headers['Authorization'] = "Bearer " + AuthSessionService.getAccessToken();
    return config;
}

// so we are not authenticated, but we still do have a refresh-token, this means, we should get a new access-token
if(AuthSessionService.hasRefreshToken()) {
    var deferred = $q.defer(),
        loginService = angular.injector(['MyApp']).get('LoginService');

    loginService.refresh().then(function(result) {
        config.headers['Authorization'] = "Bearer " + AuthSessionService.getAccessToken();
        deferred.resolve(config);
    }).catch(function() {
        deferred.reject('Failed to refresh access token');
    });

    return deferred.promise;
}

//no access-token, no refresh-token, make the call without authorization headers
return config;

但是,登录服务发出的请求似乎没有应用拦截器,因此请求转到/api/login而不是实际的 api 端点。

这是Angular的设计,当从拦截器的请求方法中发出新的http请求时不应用拦截器?

4

1 回答 1

1

你的代码流程是这样的:

0) AngularJS 定义$httpProvider

1)您定义注入loginService的依赖项;$httpProvider$http

2)你定义一个依赖loginService并改变$http工作方式的HTTP拦截器;

3)您定义其他注入的服务$http

看看这个函数,$get任何 AngularJS 提供者都必须提供的方法。每次您的服务$http作为依赖项注入并返回 $http时都会调用它。

现在,如果您返回第 396 行,您将看到在调用reversedInterceptors时构建了一个列表。$get它是一个局部变量,因此$http返回的实例将能够使用它,这就是这里的答案,是您注入reversedInterceptors的每个“实例”的不同参考。$http

因此,$http注入loginService(1) 与注入所有其他服务 (3) 的不同,不同之处在于它reversedInterceptors尚未包含您在步骤 (2) 中添加的拦截器。

关于服务与提供者。服务建立在提供者之上,基本上是这样做的:

function MyService() {
    ...
}

angular.service('MyService', MyService);

// which Angular translates to this


function MyServiceProvider() {
    var myService = new MyService();

    this.$get = function() {
        return myService;
    };
}

angular.provider('MyServiceProvider', MyServiceProvider);

虽然提供者是这样的:

function MyOtherProvider() {
    var someStuff = [1, 2, 3];

    this.$get = function() {
        var otherStuff = [5, 6, 7]; // this is how reversedInterceptors is 
                                    // initialized in `$httpProvider`

        function get(url) {
            // do stuff, maybe use otherStuff
        }

        return {
            get: get
        };
    };
}

angular.provider('MyOtherProvider', MyOtherProvider);

Angular 只实例化MyServiceProvider一次MyOtherProvider,但内部发生的事情是不同的。

于 2015-08-11T12:35:23.087 回答