Angular http拦截器
Angular http interceptor
Angular HTTP 拦截器未应用于从拦截器内初始化的请求?
在我们的代码库中,对 api 的每个请求都有一个以 /api/
开头的 url 并且我们有一个拦截器使用我们 [=] 的实际地址更新这些请求31=](使开发和生产环境之间的切换变得容易)。
在更新 url 之后,如果存在访问令牌,拦截器还会添加授权 header。这一切都很完美。
然而,有时访问令牌已过期,但我们仍然有一个刷新令牌,在继续实际请求之前,我首先想向我们的 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;
但是,login-service 发出的请求似乎没有应用拦截器,因此请求转到 /api/login
而不是实际的 api 端点。
这是 Angular 的设计,当从拦截器的请求方法中发出新的 http 请求时没有应用拦截器?
你的代码流程是这样的:
0) AngularJS 定义 $httpProvider
;
1) 你定义 loginService
依赖于 $httpProvider
来注入 $http
;
2) 你定义了一个依赖于loginService
的HTTP拦截器并改变了$http
的工作方式;
3) 您定义了其他注入 $http
.
的服务
看看this function, the $get
method any AngularJS provider must supply. It is called each time your services inject $http
as a dependency and returns $http
.
现在,如果您返回 line 396,您会看到在调用 $get
时构建了 reversedInterceptors
的列表。它是一个局部变量,因此返回的 $http
实例将能够使用它, 这就是这里的答案,reversedInterceptors
是每个 "instance" 您注射了 $http
。
因此 loginService
中注入的 $http
(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
一次,但是里面发生的事情是不一样的。
Angular HTTP 拦截器未应用于从拦截器内初始化的请求?
在我们的代码库中,对 api 的每个请求都有一个以 /api/
开头的 url 并且我们有一个拦截器使用我们 [=] 的实际地址更新这些请求31=](使开发和生产环境之间的切换变得容易)。
在更新 url 之后,如果存在访问令牌,拦截器还会添加授权 header。这一切都很完美。
然而,有时访问令牌已过期,但我们仍然有一个刷新令牌,在继续实际请求之前,我首先想向我们的 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;
但是,login-service 发出的请求似乎没有应用拦截器,因此请求转到 /api/login
而不是实际的 api 端点。
这是 Angular 的设计,当从拦截器的请求方法中发出新的 http 请求时没有应用拦截器?
你的代码流程是这样的:
0) AngularJS 定义 $httpProvider
;
1) 你定义 loginService
依赖于 $httpProvider
来注入 $http
;
2) 你定义了一个依赖于loginService
的HTTP拦截器并改变了$http
的工作方式;
3) 您定义了其他注入 $http
.
看看this function, the $get
method any AngularJS provider must supply. It is called each time your services inject $http
as a dependency and returns $http
.
现在,如果您返回 line 396,您会看到在调用 $get
时构建了 reversedInterceptors
的列表。它是一个局部变量,因此返回的 $http
实例将能够使用它, 这就是这里的答案,reversedInterceptors
是每个 "instance" 您注射了 $http
。
因此 loginService
中注入的 $http
(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
一次,但是里面发生的事情是不一样的。