#angular #angular-http-interceptors
Вопрос:
Я работаю с Angular AWS Cognito
Я смог войти в систему и мне нужно добавить токен на предъявителя cognito
@Injectable({
providedIn: 'root',
})
export class InterceptorService implements HttpInterceptor {
constructor(public loaderService: LoaderService, private router: Router) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.getToken().pipe(
mergeMap((token) => {
request = request.clone(
{
setHeaders: { Authorization: `Bearer ${token}` }
});
return next.handle(request);
})
);
}
getToken() {
return from(
new Promise((resolve, reject) => {
Auth.currentSession().then((session) => {
if (!session.isValid()) {
resolve(null);
} else {
resolve(session.getIdToken().getJwtToken());
}
}).catch(err => { return resolve(null) });
})
);
}
}
Этот код работает нормально, проблема в том, как обработать HttpResponse здесь?
Я попытался следовать коду, но это не сработало, у запроса нет токена на предъявителя
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
tap(
(event) => {
if (event instanceof HttpResponse) {
if (event.status !== 200) {
console.log('Response', event.status);
}
} else {
return this.getToken().pipe(
mergeMap((token) => {
request = request.clone(
{
setHeaders: { Authorization: `Bearer ${token}` }
});
return next.handle(request);
})
);
}
},
(error) => {
// to handle errors
}
)
}
Комментарии:
1. Пожалуйста, проверьте ссылку на демонстрационную ссылку stackblitz. Надеюсь, это вам поможет.
Ответ №1:
Насколько я знаю tap
, запускается только тогда, когда ошибки нет. Если вы хотите, чтобы ваша функция выполнялась при ошибке, которую вы должны использовать catchError()
в канале.
Ответ №2:
tap — это оператор для создания побочных эффектов, вы не можете просто вернуть наблюдаемое из обратного вызова, на него не будет подписана подписка. также немного странна логика, в которой вы отправляете исходный запрос и повторяете его с помощью токена, если он завершается неудачно. Я считаю, что вы должны добавлять токен к каждому запросу.
intercept(...) {
return this.sendWithToken(request).pipe(
catchError(error => error.status === 401 ? this.sendWithToken(request) : throwError(error)) // try one more time if return code is 401
);
}
sendWithToken(request: ...) {
return this.getToken().pipe(
mergeMap(token => addToken(request)),
mergeMap(authedRequest => next.handle(authedRequest)),
);
}
также код getToken может быть улучшен, потому что вам не нужно создавать обещание, если оно у вас уже есть
getToken() {
return from(
Auth.currentSession().then((session) => {
if (!session.isValid()) {
return null;
} else {
return session.getIdToken().getJwtToken();
}
}).catch(err => null);
);
}
Ответ №3:
Я решил эту проблему с помощью следующего кода перехватчика:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.getToken().pipe(
mergeMap((token) => {
request = request.clone(
{
headers: request.headers.set('Authorization', `Bearer ${token}`)
});
return next.handle(request).pipe(
tap(evt => {
// modify here
}),
catchError((error: any) => {
if (error amp;amp; error.status) {
if (error.status == 401) {
this.router.navigate(['/']);
}
} else {
return throwError(error);
}
})
)
})
);
}
getToken() {
return from(
Auth.currentSession().then((session) => {
if (!session.isValid()) {
return null;
} else {
return session.getIdToken().getJwtToken();
}
}).catch(err => null)
);
}