Jam*_*mes 6 javascript rxjs typescript angular-http-interceptors angular
这是AuthInterceptor:
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const Token = this.authService.getToken();
if (!Token) {
return next.handle(req);
}
// Refresh Token first
if (Token.expiresRefreshToken && Number(Token.expiresRefreshToken) < Date.now()) {
this.authService.refreshTokenRefresh(Token.tokenref)
.subscribe((response) => {
localStorage.setItem('tokenref', response.tokenref);
localStorage.setItem('tokenrefexp', response.tokenrefexp);
});
}
// Then next Access Token
if (Token.expiresToken && Number(Token.expiresToken) < Date.now()) {
this.authService.refreshToken(Token.tokenref)
.subscribe((response) => {
localStorage.setItem('token', response.token);
localStorage.setItem('tokenexp', response.tokenexp);
});
}
// Original request with updated custom headers
return next.handle(req.clone({
headers: req.headers
.set('Authorization', 'Bearer ' + localStorage.getItem('token'))
.set('X-Auth-Provider', localStorage.getItem('provider'))
}));
}
}Run Code Online (Sandbox Code Playgroud)
我需要在发送请求之前评估这些条件,因为一些自定义标头可能会在方法refreshToken和之后发生变化refreshTokenRefresh.有没有办法评估RxJS运算符内的所有内容?第一个条件(refreshTokenRefresh),然后第二个(refreshToken),最后是req.
更新:我收到此错误:RangeError: Maximum call stack size exceeded.如何解决此问题?
我们希望等到某些请求完成(评估顺序并不重要?)而不是执行另一个请求。
const queue = this.handleRefreshToke(this.handleRefreshTokenRefresh([]));- 在我们打电话之前,将所有应完成的请求放在那里next.handle。使用forkJoin等待所有请求(放入队列中)完成,然后映射到另一个 Obervable ( mergeMap)。
PS 我们还可以将handleRefreshTokenRefresh和handleRefreshToke移至单独的 HttpInterceptor。
编辑为了防止拦截器的递归调用,我们应该跳过刷新令牌调用的拦截器。
export const InterceptorSkipHeader = 'X-Skip-Interceptor';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) { }
handleRefreshTokenRefresh(queue: Observable<void>[]) {
const Token = this.authService.getToken();
if (Token.expiresRefreshToken &&
const req = this.authService.refreshTokenRefresh(Token.tokenref)
.pipe(tap((response) => {
localStorage.setItem('tokenref', response.tokenref);
localStorage.setItem('tokenrefexp', response.tokenrefexp);
}));
return [...queue, req];
}
return queue;
}
handleRefreshToke(queue: Observable<void>[]) {
const Token = this.authService.getToken();
if (Token.expiresToken && Number(Token.expiresToken) < Date.now()) {
const req = this.authService.refreshToken(Token.tokenref)
.subscribe((response) => {
localStorage.setItem('token', response.token);
localStorage.setItem('tokenexp', response.tokenexp);
});
return [...queue, req];
}
return queue;
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.headers.has(InterceptorSkipHeader)) {
const headers = req.headers.delete(InterceptorSkipHeader);
return next.handle(req.clone({ headers }));
}
const Token = this.authService.getToken();
if (!Token) {
return next.handle(req);
}
const queue = this.handleRefreshToke(this.handleRefreshTokenRefresh([]));
return forkJoin(queue).pipe(
mergeMap(()=>{
return next.handle(req.clone({
headers: req.headers
.set('Authorization', 'Bearer ' + localStorage.getItem('token'))
.set('X-Auth-Provider', localStorage.getItem('provider')),
}));
})
);
}
}
Run Code Online (Sandbox Code Playgroud)
添加InterceptorSkipHeader到refreshTokens以跳过拦截器。
// AuthService
refreshTokenRefresh(token){
const headers = new HttpHeaders().set(InterceptorSkipHeader, '');
return this.httpClient
.get(someUrl, { headers })
}
refreshToken(token){
const headers = new HttpHeaders().set(InterceptorSkipHeader, '');
return this.httpClient
.get(someUrl, { headers })
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
547 次 |
| 最近记录: |