推送http拦截器时的循环依赖
Circular dependency while pushing http interceptor
我正在使用 http 拦截器来拦截我应用程序中的每个 http 请求。
但是我发现 循环依赖:$http <- APIInterceptor <- $http <- $templateRequest <- $compile
这是我的服务代码:
mPosServices.factory('mosServiceFactory', function ($http, $rootScope, $cookies, $q) {
return{
refresh_token: function () {
var refreshToken = $http({
method: "get",
url: "myservice/oauth/token?grant_type=refresh_token&client_id=restapp&client_secret=restapp&refresh_token=" + $cookies.get('refresh_token'),
})
return refreshToken;
}
});
mPosServices.service('APIInterceptor', ['mosServiceFactory','$cookies',function (mosServiceFactory,$cookies) {
var service = this;
service.request = function (config) {
if (!$cookies.get('access_token')) { //if access_token cookie does not exist
mosServiceFactory.refresh_token().then(function (response) {
var date = new Date();
date.setTime(date.getTime() + (response.data.expiresIn * 1000));
$cookies.remove('access_token');
$cookies.put('access_token', response.data.value, {expires: date});
$cookies.put('refresh_token', response.data.refreshToken.value);
}); //call the refresh_token function first
}
return config;
};
service.responseError = function (response) {
return response;
};
}]);
并将其推送为:
$httpProvider.interceptors.push('APIInterceptor');
在配置函数中。
我在这里做错了什么吗?
即使我尝试使用
手动注入 $http
$injector
,但得到同样的错误。
请帮助我。
你确实需要添加 use $injector
to get mosServiceFactory
instance inside of interceptor。但这不是您需要做的全部。您还需要确保您不会陷入无限请求循环,因为拦截器也会发出请求。您可以做的是检查当前请求是否是令牌刷新请求,如果是,请不要再触发一个请求,我正在为此检查 URL。
还有一件重要的事要提。您需要 return 从解析为原始请求的拦截器承诺对象 config
。这样可以保证在检索令牌后重新发出拦截的请求。
全部看起来像这样:
mPosServices.service('APIInterceptor', ['$injector', '$cookies', function($injector, $cookies) {
var service = this;
service.request = function(config) {
if (!$cookies.get('access_token') && config.url.indexOf('myservice/oauth/token?grant_type=') === -1) {
return $injector.get('mosServiceFactory').refresh_token().then(function(response) {
var date = new Date();
date.setTime(date.getTime() + (response.data.expiresIn * 1000));
$cookies.remove('access_token');
$cookies.put('access_token', response.data.value, {
expires: date
});
$cookies.put('refresh_token', response.data.refreshToken.value);
}).then(function() {
return config; // <-- token is refreshed, reissue original request
});
}
return config;
};
service.responseError = function(response) {
return response;
};
}]);
查看我正在测试解决方案的演示,了解它如何在加载令牌后恢复原始请求。
我正在使用 http 拦截器来拦截我应用程序中的每个 http 请求。 但是我发现 循环依赖:$http <- APIInterceptor <- $http <- $templateRequest <- $compile
这是我的服务代码:
mPosServices.factory('mosServiceFactory', function ($http, $rootScope, $cookies, $q) {
return{
refresh_token: function () {
var refreshToken = $http({
method: "get",
url: "myservice/oauth/token?grant_type=refresh_token&client_id=restapp&client_secret=restapp&refresh_token=" + $cookies.get('refresh_token'),
})
return refreshToken;
}
});
mPosServices.service('APIInterceptor', ['mosServiceFactory','$cookies',function (mosServiceFactory,$cookies) {
var service = this;
service.request = function (config) {
if (!$cookies.get('access_token')) { //if access_token cookie does not exist
mosServiceFactory.refresh_token().then(function (response) {
var date = new Date();
date.setTime(date.getTime() + (response.data.expiresIn * 1000));
$cookies.remove('access_token');
$cookies.put('access_token', response.data.value, {expires: date});
$cookies.put('refresh_token', response.data.refreshToken.value);
}); //call the refresh_token function first
}
return config;
};
service.responseError = function (response) {
return response;
};
}]);
并将其推送为:
$httpProvider.interceptors.push('APIInterceptor');
在配置函数中。 我在这里做错了什么吗? 即使我尝试使用
手动注入 $http$injector
,但得到同样的错误。 请帮助我。
你确实需要添加 use $injector
to get mosServiceFactory
instance inside of interceptor。但这不是您需要做的全部。您还需要确保您不会陷入无限请求循环,因为拦截器也会发出请求。您可以做的是检查当前请求是否是令牌刷新请求,如果是,请不要再触发一个请求,我正在为此检查 URL。
还有一件重要的事要提。您需要 return 从解析为原始请求的拦截器承诺对象 config
。这样可以保证在检索令牌后重新发出拦截的请求。
全部看起来像这样:
mPosServices.service('APIInterceptor', ['$injector', '$cookies', function($injector, $cookies) {
var service = this;
service.request = function(config) {
if (!$cookies.get('access_token') && config.url.indexOf('myservice/oauth/token?grant_type=') === -1) {
return $injector.get('mosServiceFactory').refresh_token().then(function(response) {
var date = new Date();
date.setTime(date.getTime() + (response.data.expiresIn * 1000));
$cookies.remove('access_token');
$cookies.put('access_token', response.data.value, {
expires: date
});
$cookies.put('refresh_token', response.data.refreshToken.value);
}).then(function() {
return config; // <-- token is refreshed, reissue original request
});
}
return config;
};
service.responseError = function(response) {
return response;
};
}]);
查看我正在测试解决方案的演示,了解它如何在加载令牌后恢复原始请求。