응답 가로채기에서 요청을 다시 보내려면 어떻게 해야 하나요?
응용 프로그램에서 세션 손실을 감지하는 인터셉터를 만들었습니다(서버는 HTTP 419를 전송합니다).이 경우 서버에 새로운 세션을 요청해야 하며, 그 후 자동으로 원래 요청을 다시 보내고 싶습니다.
요청 대행 수신기에 요청을 저장하고 다시 보낼 수도 있지만, 더 간단한 해결책이 있을 수도 있습니다.
세션을 작성하려면 특정 웹 서비스를 사용해야 합니다.
angular.module('myapp', [ 'ngResource' ]).factory(
'MyInterceptor',
function ($q, $rootScope) {
return function (promise) {
return promise.then(function (response) {
// do something on success
return response;
}, function (response) {
if(response.status == 419){
// session lost
// create new session server-side
// Session.query();
// then send current request again
// ???
}
return $q.reject(response);
});
};
}).config(function ($httpProvider) {
$httpProvider.responseInterceptors.push('MyInterceptor');
});
여기 관심 있는 분들을 위한 약속을 이용한 저의 해결 방법이 있습니다.기본적으로 새 세션을 요청하고 응답을 기다린 후 원래 요청에 대응하는 새 요청을 전송해야 합니다(response.config 사용).약속 $http(response.config)를 반환하면 응답이 원래 요청과 동일하게 처리됩니다.
(약속은 처음이라 별로일 수 있습니다)
angular.module('myapp', [ 'ngResource' ]).factory(
'MyInterceptor',
function ($q, $rootScope) {
return function (promise) {
return promise.then(function (response) {
// do something on success
return response;
}, function (response) {
if(response.status == 419){
// session lost
var Session = $injector.get('Session');
var $http = $injector.get('$http');
// first create new session server-side
var defer = $q.defer();
var promiseSession = defer.promise;
Session.query({},function(){
defer.resolve();
}, function(){
// error
defer.reject();
});
// and chain request
var promiseUpdate = promiseSession.then(function(){
return $http(response.config);
});
return promiseUpdate;
}
return $q.reject(response);
});
};
}).config(function ($httpProvider) {
$httpProvider.responseInterceptors.push('MyInterceptor');
});
그responseError
의 방법httpInterceptor
다음과 같이 해야 합니다.
responseError: function (response) {
// omit the retry if the request is made to a template or other url
if (response.config.apiCal === true) {
if (response.status === 419) {
var deferred = $q.defer();
// do something async: try to login.. rescue a token.. etc.
asyncFuncionToRecoverFrom419(funcion(){
// on success retry the http request
retryHttpRequest(response.config, deferred);
});
return deferred.promise;
} else {
// a template file...
return response;
}
}
}
마법은 여기서 일어납니다.
function retryHttpRequest(config, deferred){
function successCallback(response){
deferred.resolve(response);
}
function errorCallback(response){
deferred.reject(response);
}
var $http = $injector.get('$http');
$http(config).then(successCallback, errorCallback);
}
올바른 경로입니다. 기본적으로 요청을 큐에 저장하고 세션을 재정립한 후 다시 시도합니다.
일반적인 모듈인 angular http auth(https://github.com/witoldsz/angular-http-auth)를 참조하십시오.이 모듈에서는 401개의 응답을 가로채지만 이 접근법에 따라 솔루션을 모델링할 수 있습니다.
거의 동일한 솔루션, 타이프 스크립트로 번역:
/// <reference path="../app.ts" />
/// <reference path="../../scripts/typings/angularjs/angular.d.ts" />
class AuthInterceptorService {
static serviceId: string = "authInterceptorService";
constructor(private $q: ng.IQService, private $location: ng.ILocationService, private $injector, private $log: ng.ILogService, private authStatusService) {}
// Attenzione. Per qualche strano motivo qui va usata la sintassi lambda perché se no ts sbrocca il this.
public request = (config: ng.IRequestConfig) => {
config.headers = config.headers || {};
var s: AuthStatus = this.authStatusService.status;
if (s.isAuth) {
config.headers.Authorization = 'Bearer ' + s.accessToken;
}
return config;
}
public responseError = (rejection: ng.IHttpPromiseCallbackArg<any>) => {
if (rejection.status === 401) {
var that = this;
this.$log.warn("[AuthInterceptorService.responseError()]: not authorized request [401]. Now I try now to refresh the token.");
var authService: AuthService = this.$injector.get("authService");
var $http: ng.IHttpService = this.$injector.get("$http");
var defer = this.$q.defer();
var promise: ng.IPromise<any> = defer.promise.then(() => $http(rejection.config));
authService
.refreshAccessToken()
.then((response) => {
that.$log.info("[AuthInterceptorService.responseError()]: token refreshed succesfully. Now I resend the original request.");
defer.resolve();
},
(err) => {
that.$log.warn("[AuthInterceptorService.responseError()]: token refresh failed. I need to logout, sorry...");
this.authStatusService.clear();
this.$location.path('/login');
});
return promise;
}
return this.$q.reject(rejection);
}
}
// Update the app variable name to be that of your module variable
app.factory(AuthInterceptorService.serviceId,
["$q", "$location", "$injector", "$log", "authStatusService", ($q, $location, $injector, $log, authStatusService) => {
return new AuthInterceptorService($q, $location, $injector, $log, authStatusService)
}]);
이게 도움이 됐으면 좋겠다.
언급URL : https://stackoverflow.com/questions/18638211/how-can-i-send-request-again-in-response-interceptor
'programing' 카테고리의 다른 글
WooCommerce에서 프로그래밍 방식으로 고객 과금 정보 업데이트 (0) | 2023.03.28 |
---|---|
상위 범위에서 ng 포함 양식의 유효성을 어떻게 확인할 수 있습니까? (0) | 2023.03.28 |
React에서 휴식 후 전화를 거는 방법JS 코드? (0) | 2023.03.28 |
JSON을 Flutter로 디코딩하는 방법 (0) | 2023.03.28 |
컨트롤러에서 json 및 xml을 반환하는 스프링 부트 (0) | 2023.03.23 |