https://medium.com/angular-in-depth/top-10-ways-to-use-interceptors-in-angular-db450f8a62d6
import { Injectable } from "@angular/core";
import { | |
HttpEvent, HttpInterceptor, HttpHandler, | |
HttpRequest, HttpErrorResponse | |
} from "@angular/common/http"; | |
import { throwError, Observable, BehaviorSubject, of } from "rxjs"; | |
import { catchError, filter, take, switchMap } from "rxjs/operators"; | |
@Injectable() | |
export class AuthInterceptor implements HttpInterceptor { | |
private AUTH_HEADER = "Authorization"; | |
private token = "secrettoken"; | |
private refreshTokenInProgress = false; | |
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null); | |
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | |
if (!req.headers.has('Content-Type')) { | |
req = req.clone({ | |
headers: req.headers.set('Content-Type', 'application/json') | |
}); | |
} | |
req = this.addAuthenticationToken(req); | |
return next.handle(req).pipe( | |
catchError((error: HttpErrorResponse) => { | |
if (error && error.status === 401) { | |
// 401 errors are most likely going to be because we have an expired token that we need to refresh. | |
if (this.refreshTokenInProgress) { | |
// If refreshTokenInProgress is true, we will wait until refreshTokenSubject has a non-null value | |
// which means the new token is ready and we can retry the request again | |
return this.refreshTokenSubject.pipe( | |
filter(result => result !== null), | |
take(1), | |
switchMap(() => next.handle(this.addAuthenticationToken(req))) | |
); | |
} else { | |
this.refreshTokenInProgress = true; | |
// Set the refreshTokenSubject to null so that subsequent API calls will wait until the new token has been retrieved | |
this.refreshTokenSubject.next(null); | |
return this.refreshAccessToken().pipe( | |
switchMap((success: boolean) => { | |
this.refreshTokenSubject.next(success); | |
return next.handle(this.addAuthenticationToken(req)); | |
}), | |
// When the call to refreshToken completes we reset the refreshTokenInProgress to false | |
// for the next time the token needs to be refreshed | |
finalize(() => this.refreshTokenInProgress = false) | |
); | |
} | |
} else { | |
return throwError(error); | |
} | |
}) | |
); | |
} | |
private refreshAccessToken(): Observable<any> { | |
return of("secret token"); | |
} | |
private addAuthenticationToken(request: HttpRequest<any>): HttpRequest<any> { | |
// If we do not have a token yet then we should not set the header. | |
// Here we could first retrieve the token from where we store it. | |
if (!this.token) { | |
return request; | |
} | |
// If you are calling an outside domain then do not add the token. | |
if (!request.url.match(/www.mydomain.com\//)) { | |
return request; | |
} | |
return request.clone({ | |
headers: request.headers.set(this.AUTH_HEADER, "Bearer " + this.token) | |
}); | |
} | |
} |
Không có nhận xét nào:
Đăng nhận xét