Вот 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'))
}));
}
}Мне нужно оценить эти условия перед отправкой запроса, потому что некоторые настраиваемые заголовки могут измениться после методов refreshToken и refreshTokenRefresh. Есть ли способ оценить все внутри оператора RxJS? Первое состояние (refreshTokenRefresh), затем второе (refreshToken) и, наконец, req.
Обновление: я получаю эту ошибку: RangeError: Maximum call stack size exceeded. Как это исправить?
Вы можете прочитать RxJS, где находится оператор If-Else?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Мы хотим подождать, пока некоторые запросы будут выполнены (порядок оценки не имеет значения?), Чем выполнить другой запрос.
const queue = this.handleRefreshToke(this.handleRefreshTokenRefresh([])); - поместите туда все запросы, которые должны быть выполнены до того, как мы вызовем next.handle.
Используйте forkJoin, чтобы дождаться завершения всех запросов (помещенных в очередь), а затем сопоставить их с другим Obervable (mergeMap).
PS Мы также можем переместить handleRefreshTokenRefresh и handleRefreshToke в отдельный HttpInterceptor.
РЕДАКТИРОВАТЬ Чтобы предотвратить рекурсивный вызов перехватчиков, мы должны пропустить перехватчики для вызова refreshTokens.
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')),
}));
})
);
}
}
Добавьте 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 })
}
порядок оценки имеет значение, потому что мне нужен действующий токен обновления (первое условие) для создания токена доступа (второе условие).
Вы можете использовать concat вместо forkJoin
вы можете подтвердить мой ответ? Я думаю, что что-то не так, потому что мой сервер немного нестабилен: много раз перезагружается при использовании перехватчика. Я получаю эту ошибку на консоли RangeError: Maximum call stack size exceeded.
Вам нужно пропустить перехватчик для handleRefreshToken и handleRefreshTokenRefresh .
Спасибо! Раньше я пытался перестать вызывать перехватчик с HttpBackEnd, но это не сработало.
Просто поместите последнюю часть кода в
elseи поместитеnext.handleв своиif.