我正在尝试拦截 401 响应,在再次尝试请求之前发送刷新令牌请求(但使用不同的标头)。我让它工作,除了retryWhen
不让我修改原始请求标头。所以我一直在尝试使用catchError
,但我似乎无法再次执行请求。
这是我目前的retryWhen
:
import {Injectable} from '@angular/core';
import {
HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse
}
from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {CustomerService} from "../customer/customer.service";
import * as ApplicationSettings from "application-settings";
import {retryWhen, map} from "rxjs/operators";
import {LoginResponse} from "./LoginResponse";
/**
* This takes a request that requires an access_token and refreshes it on 401 errors.
*/
@Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
public constructor(private customer: CustomerService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
retryWhen(errors => {
return Observable.create(observer => {
errors.forEach((error: HttpErrorResponse) => {
if (error.status === 401) {
let refresh_token = ApplicationSettings.getString('refresh_token');
return this.customer.refreshToken(refresh_token).subscribe(
(response: LoginResponse) => {
this.customer.setToken(response);
let headers = req.headers.set('Authorization', `Bearer ${response.access_token}`);
console.log(`Bearer ${response.access_token}`);
let newReq = req.clone({headers: headers});
observer.next(next.handle(newReq));
observer.complete();
},
error2 => {
observer.error();
}
);
} else {
observer.error();
}
});
});
})
);
}
}
如果我换掉retryWhen
:catchError
catchError((err, caught) => {
console.log('err: ' + JSON.stringify(err));
if (err.status === 401) {
console.log('401 !!!! REFRESH MEH!');
let newReqOb: Observable<HttpEvent<any>> = Observable.create(observer => {
console.log('going to refresh token');
let refresh_token = ApplicationSettings.getString('refresh_token');
let refresh = this.customer.refreshToken(refresh_token);
refresh.subscribe((response: LoginResponse) => {
console.log('token refreshed!');
this.customer.setToken(response);
let access_token = ApplicationSettings.getString('access_token');
let headers = req.headers.set('Authorization', `Bearer ${access_token}`);
console.log(`Bearer ${access_token}`);
let newReq = req.clone({headers: headers});
observer.next(next.handle(newReq)); // <-- HERE IT WONT FIRE
observer.complete();
});
});
return newReqOb;
}
return caught;
})
重要的是我要回来next.handle(newReq)
了,它似乎没有触发请求。如果我将其切换为next.handle(newReq).subscribe()
,请求将触发但不会触发回调。
这是完整的示例retryWhen
:
import {Inject, Injectable} from '@angular/core';
import {
HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse, HttpClient
}
from '@angular/common/http';
import {Observable, ObservableInput} from 'rxjs/Observable';
import {CustomerService} from "../customer/customer.service";
import * as ApplicationSettings from "application-settings";
import {retryWhen, map, catchError} from "rxjs/operators";
import {LoginResponse} from "./LoginResponse";
import {APP_CONFIG, AppConfig} from "../../app.config";
/**
* This takes a request that requires an access_token and refreshes it on 401 errors.
*/
@Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
public constructor(private customer: CustomerService, private http: HttpClient, @Inject(APP_CONFIG) private config: AppConfig) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((err, caught) => {
console.log('err: ' + JSON.stringify(err));
if (err.status === 401) {
console.log('401 !!!! REFRESH MEH!');
let newReqOb: Observable<HttpEvent<any>> = Observable.create(observer => {
console.log('going to refresh token');
let refresh_token = ApplicationSettings.getString('refresh_token');
let refresh = this.customer.refreshToken(refresh_token);
refresh.subscribe((response: LoginResponse) => {
console.log('token refreshed!');
this.customer.setToken(response);
let access_token = ApplicationSettings.getString('access_token');
let headers = req.headers.set('Authorization', `Bearer ${access_token}`);
console.log(`Bearer ${access_token}`);
let newReq = req.clone({headers: headers});
observer.next(next.handle(newReq));
observer.complete();
});
});
return newReqOb;
}
return caught;
})
);
}
}