Angular拦截器,处理HTTP错误并重试
Angular interceptor, handle HTTP Error and retry
我有一个基本的 JWT 系统,以及一个检查请求是否因未授权而失败的拦截器。
import {Injectable} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {AuthService} from '../services/auth.service';
import {catchError, retryWhen} from 'rxjs/operators';
@Injectable()
export class AuthenticationErrorInterceptor implements HttpInterceptor {
private readonly _authService: AuthService;
constructor(authService: AuthService) {
this._authService = authService;
}
public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authReq = req.clone({headers: req.headers});
return next.handle(authReq)
.pipe(
catchError((err) => this._handleAuthError(err)),
retry(3)
);
}
private _handleAuthError(error: HttpErrorResponse): Observable<any> {
if (error.status === 401 || error.status === 403) {
return this._authService.authenticate();
}
return throwError(error);
}
}
如果请求确实失败,那么我想在调用 this._authService.authenticate();
后重新发送请求。它将重新进行身份验证,因为错误处理迫使它重新进行身份验证,但在我刷新浏览器之前它不会回忆起导致应用程序失败的请求。
我怎样才能让我的守卫再次尝试请求?
我也尝试过使用 retryWhen
,但我得到了 same/similar 结果。
在您拥有 re-authenticated 您的 session 之后,在 HTTP 处理程序上调用 .next。理想情况下,您应该 return 来自您的身份验证方法的身份验证令牌,然后可以将其附加到请求 auth headers.
import {Injectable} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {AuthService} from '../services/auth.service';
import {catchError, retryWhen} from 'rxjs/operators';
@Injectable()
export class AuthenticationErrorInterceptor implements HttpInterceptor {
private readonly _authService: AuthService;
constructor(authService: AuthService) {
this._authService = authService;
}
public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 401 || error.status === 403) {
return this._authService.authenticate()
.pipe(
mergeMap((token) => next.handle(req.clone({
headers: req.headers.set(AUTH_TOKEN_NAME_HERE, token)
})))
);
}
return throwError(error);
})
);
}
}
我有一个基本的 JWT 系统,以及一个检查请求是否因未授权而失败的拦截器。
import {Injectable} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {AuthService} from '../services/auth.service';
import {catchError, retryWhen} from 'rxjs/operators';
@Injectable()
export class AuthenticationErrorInterceptor implements HttpInterceptor {
private readonly _authService: AuthService;
constructor(authService: AuthService) {
this._authService = authService;
}
public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authReq = req.clone({headers: req.headers});
return next.handle(authReq)
.pipe(
catchError((err) => this._handleAuthError(err)),
retry(3)
);
}
private _handleAuthError(error: HttpErrorResponse): Observable<any> {
if (error.status === 401 || error.status === 403) {
return this._authService.authenticate();
}
return throwError(error);
}
}
如果请求确实失败,那么我想在调用 this._authService.authenticate();
后重新发送请求。它将重新进行身份验证,因为错误处理迫使它重新进行身份验证,但在我刷新浏览器之前它不会回忆起导致应用程序失败的请求。
我怎样才能让我的守卫再次尝试请求?
我也尝试过使用 retryWhen
,但我得到了 same/similar 结果。
在您拥有 re-authenticated 您的 session 之后,在 HTTP 处理程序上调用 .next。理想情况下,您应该 return 来自您的身份验证方法的身份验证令牌,然后可以将其附加到请求 auth headers.
import {Injectable} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {AuthService} from '../services/auth.service';
import {catchError, retryWhen} from 'rxjs/operators';
@Injectable()
export class AuthenticationErrorInterceptor implements HttpInterceptor {
private readonly _authService: AuthService;
constructor(authService: AuthService) {
this._authService = authService;
}
public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 401 || error.status === 403) {
return this._authService.authenticate()
.pipe(
mergeMap((token) => next.handle(req.clone({
headers: req.headers.set(AUTH_TOKEN_NAME_HERE, token)
})))
);
}
return throwError(error);
})
);
}
}