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 回答
你的代码流是这样的:
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)中添加的拦截器 .关于服务与提供商 . 服务是基于提供者构建的,基本上是这样做的:
虽然供应商是这样的:
Angular只实例化
MyServiceProvider
和MyOtherProvider
一次,但内部发生的事情是不同的 .