Reputation: 3318
I'm using JWT and I have this logic:
Al this procedure has to be hidden to the user. I already catch the 401 status code and repeated the original call after retrieve the new token, the problem is to return the result to the original call. This is the service with the http request:
getListCategories(){
return this.http.get<Category[]>("/api/configuration/category").pipe(
catchError(err => this.handleError.handleError(err, { severity: 'error', summary: 'Error retrieving the list of categories', life: 5000 }))
);
}
this is the error interceptor that make the refresh call and repeat the original call:
export class ErrorInterceptorService implements HttpInterceptor {
constructor(private auth: AuthService, public router: Router) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { shouldRetry } = this;
return next.handle(request).pipe(
retryWhen(genericRetryStrategy({
shouldRetry
})),
catchError(err => {
//401 the token is invalid so I have to refresh it
if (err.status === 401 && request.url !== "/api/login") {
this.auth.refreshToken().subscribe(
(apiResult: SessionTokenResponse) => {
this.auth.saveToken(apiResult.token);
request = request.clone({ headers: request.headers.set('Authorization', 'Bearer ' + apiResult.token) });
next.handle(request).subscribe();
},
);
} else if (err.status === 401 && request.url === "/api/login") {
this.auth.logout()
}else{
const error = err.error.message || err.statusText;
return throwError(error);
}
}),
)
}
private shouldRetry = (error) => (error.error instanceof ErrorEvent);
}
The problem is in the service, it doesn't wait the remake call but exit after the first error. Can you help me?Thanks
Upvotes: 0
Views: 111
Reputation: 32507
You want to return Observable
with chain operations that included extra request between original request and repeted one. I would try to do this using switchMap
.
It would be something like this:
catchError(err => {
if (err.status === 401 && request.url !== "/api/login") {
//by returning observable here, you are "chaining" the calls so original caller will get this observable's result. `catchError` can be threated like `catch` block in `try-catch` where you can still do operations and return results - ergo continue operations.
return this.auth.refreshToken()
.switchMap( // this just switches from one observable to another
(apiResult: SessionTokenResponse) => {
this.auth.saveToken(apiResult.token);
request = request.clone({ headers: request.headers.set('Authorization', 'Bearer ' + apiResult.token) });
return next.handle(request); // return original request handler with updated headers
},
);
Obviously not tested and might be syntax invalid as written here.
Upvotes: 1