首页 文章

Angular http拦截器

提问于
浏览
3

Angular http拦截器未应用于拦截器内初始化的请求?

在我们的代码库中,对api的每个请求都有一个以 /api/ 开头的url,我们有一个拦截器,用我们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 endpoints .

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

1 回答

  • 1

    你的代码流是这样的:

    0)AngularJS定义 $httpProvider ;

    1)你定义 loginService ,这取决于 $httpProvider 注入 $http ;

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

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

    看一下this函数,任何AngularJS提供者必须提供的 $get 方法 . 每次您的服务将 $http 作为依赖项和returns $http 时调用它 .

    现在,如果你回到line 396,你会看到 reversedInterceptors 的列表是在调用 $get 时构建的 . 它是一个局部变量,因此返回的 $http 实例将能够使用它,这就是答案, reversedInterceptors 是您注入的每个"instance"的不同引用 .

    因此 loginService (1)中注入的 $http 与所有其他服务(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只实例化 MyServiceProviderMyOtherProvider 一次,但内部发生的事情是不同的 .

相关问题