我有一个拦截器,可以处理错误并对错误做出反应。如果有错误,它将执行Observable.throw(err)
。
现在,我需要一个拦截器,该拦截器捕获401
状态,然后获取存储的刷新令牌并创建新的访问令牌,在authorization
上设置req
标头,然后再次尝试失败的请求带有新标题。
这是第一个错误拦截器,请注意Observable.throw(err)
部分:
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(
private config: Config
) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.pipe(
catchError((err) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
this.config.onUnauthorized(err);
}
else {
this.config.onHttpError(err);
}
}
return Observable.throw(err);
}
)
);
}
}
这是第二个拦截器:
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private api: Api, private cs: ClientStorage, private router: Router) { }
private getNewAccessToken(req: HttpRequest<any>, next: HttpHandler) {
console.log(0);
return this.api.post<any>('token', null, {
grant_type: 'refresh_token',
refresh_token: this.cs.getItem(AppConstants.appState).refreshToken,
scope: 'user'
});
}
private appendAccessToken(req, token) {
console.log(1, token)
return req.clone({
setHeaders: {
authorization: `Bearer ${token}`
}
});
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const appState = this.cs.getItem(AppConstants.appState);
const accessToken = appState ? appState.accessToken : null;
return next.handle(this.appendAccessToken(req, accessToken))
.pipe(
catchError((error: any) => {
console.log(error);
if (error instanceof HttpErrorResponse) {
if (error.status === 401) {
console.log('Unauthorized');
return this.getNewAccessToken(req, next)
.pipe(
mergeMap((res) => {
this.cs.setItem(AppConstants.appState, {...appState, accessToken: res.access_token});
return next.handle(this.appendAccessToken(req, res.access_token));
})
);
}
else if (error.status === 403) {
this.router.navigate(['/login']);
}
}
else {
console.log(3)
return Observable.throw(error);
}
})
);
}
};
这里的问题是我添加的拦截器似乎没有执行任何操作,它初始化并拦截了不是错误但catchError
位没有的http请求”如果有错误,则运行。 catchError
中的ErrorInterceptor
运行正常,因此我相信它们会相互干扰。
如何使令牌拦截器按预期工作?
答案 0 :(得分:0)
我试图实现类似的情况。它按预期工作。这是StackBlitz Demo。
这样,我看不到您的代码有任何问题,但是我想知道为什么您将“ req”和“ next”传递给了 getNewAccessToken()方法。在该方法中未使用它们。