我使用ngrx来存储我的会话信息(令牌本身及其有效期)。 http管道中有两个拦截器:拦截器1将存储中的令牌注入到http请求中,拦截器2从响应中读取一个自定义的HTTP标头“ X-Session-Expiration”,并将其放置在存储中(我也有两个在一个拦截器中执行操作,也不能解决问题)。
intercept(request: HttpRequest, next: HttpHandler): Observable> { return this.store.select(SessionSelectors.sessionToken).pipe( first(), mergeMap(token => { console.log("interceptor 1"); if (token) { request = request.clone({ headers: request.headers.set('Authorization', 'User ' + token) }); } return next.handle(request); }) ); }
intercept(request: HttpRequest, next: HttpHandler): Observable> { return next.handle(request).pipe(map((event: HttpEvent) => { if (event instanceof HttpResponse) { console.log("interceptor 2"); if (event.headers.has("X-Session-Expiration")) { var value = event.headers.get("X-Session-Expiration"); var expiration = new Date(value); this.store.dispatch(new SessionActions.RefreshSessionExpiration({ newExpirationDate: expiration })); } return event; })); }
这将创建一个无限循环。拦截器2中的store修改会触发拦截器1中的订阅,从而触发http请求,从而触发拦截器2,依此类推。
为防止这种情况,我在拦截器1中插入了first()或take(1),但似乎没有任何改变。
答案 0 :(得分:0)
尝试在拦截器的开头添加 if 语句
intercept(request: HttpRequest, next: HttpHandler): Observable> {
if (request.url === 'api/refresh-token') {
return next.handle(request);
}
return this.store.select(SessionSelectors.sessionToken).pipe(
mergeMap(token => {
.....
}
return next.handle(requestWithToken);
})
);
}