我在前端使用带有TypeScript的Angular 2。我正在尝试实现一个http拦截器,它在每个请求上设置授权头。如果访问令牌过期,我试图重试请求,在重试之前获取带有刷新令牌的新访问令牌并更改当前请求的标头。
如何在retryWhen运算符中更新请求标头?
例如,这里是HttpInterceptor:
export class HttpInterceptor extends Http {
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return super.get(url, this.setRequestAuthorizationHeader(options)).retryWhen((errors: any) => this.errorHandler(errors));
}
private setRequestAuthorizationHeader(options?: RequestOptionsArgs): RequestOptionsArgs {
// some checks
// get accessToken from localStorage
options.headers.append('Authorization', 'Bearer ' + accessToken);
}
private errorHandler(errors) {
return errors.switchMap((err) => {
if (err.status === 401) {
let closedSubject = new Subject();
this.authenticationService.refreshToken()
.subscribe(data => {
// How to update authorization header? This doesn't work.
this.defaultOptions.headers.append('Authorization', 'Bearer ' + data.accessToken);
closedSubject.next();
});
return <any>closedSubject;
}
else {
return Observable.throw(err.json());
}
});
}
}
答案 0 :(得分:3)
我会使用catch
代替retryWhen
,因为后者会重播相同的observable,并且参数已经设置好。
顺便说一句,你的主题在errorHanlder
:
export class HttpInterceptor extends Http {
get(url: string, options ? : RequestOptionsArgs): Observable < Response > {
return super.get(url, this.setRequestAuthorizationHeader(options)).catch(errors => this.errorHandler(errors, url, options))
});
}
private setRequestAuthorizationHeader(options ? : RequestOptionsArgs): RequestOptionsArgs {
// some checks
// get accessToken from localStorage
options.headers.append('Authorization', 'Bearer ' + accessToken);
return options
}
private errorHandler(err: any, url: string, options ? : RequestOptionsArgs) {
if (err.status === 401) {
return this.authenticationService.refreshToken()
.switchMap(data => {
// save accessToken to localStorage
return super.get(url, this.setRequestAuthorizationHeader(options));
});
}
return Observable.throw(err.json());
}
另请注意,使用类似this.defaultOptions
的状态可能不是您的最佳选择,使用anobservable会更合适。