CatchError is completelly ignored in 401 response.
I have httpInterceptor that handles oauth2 authentication.
Relevant code is :
import { filter, take, switchMap, map, catchError } from 'rxjs/operators';
//ommited
if (authService.hasRefreshToken()) {
return authService.doRefreshToken().pipe(switchMap(tokenResponse => {
const accessToken = tokenResponse['access_token'];
this.tokenSubject.next(accessToken);
return <Observable<HttpEvent<any>>> next.handle(this.addToken(req, accessToken));
}), catchError((err: any, caught: any) => {
console.log(err)
return Observable.throw(err);
})
)
}
AuthService class:
export class AuthService {
doRefreshToken() {
//ommited
return this.httpClient.post(environment.baseUrl + this.tokenEndpoint, null, requestOptions).pipe(
map(tokenResponse => {
this.saveToken(tokenResponse);
return tokenResponse;
}),
catchError((err: any, caught: Observable<Object>) => {
//refreshing token failed (refrech token invalid or expired) redirect to login and wipe everything
this.logout();
return Observable.throw(err);
}));
}
}
Everything works fine for 200 response, but 401 error is completely ignored. Am i using this new catchError the wrong way ?
P.S. this piece of code was working just fine with plain old catch , but now when i migrated to angular6 pipe and catchError same stuff just doesnt work.
EDIT :
Breakpoint on catchError reveals
"SyntaxError: Unexpected end of input at AuthService.push../src/app/common/auth/auth.service.ts.AuthService.doRefreshToken
Actual response from the server is :
{
"error" : "invalid_token",
"error_description" : "Refresh token expired"
}
Headers :
Request Method: POST
Status Code: 401
The basic way to handle errors in Angular is to use Angular's HttpClient service along with RxJS operators throwError and catchError. The HTTP request is made, and it returns the data with a response if anything wrong happens then it returns an error object with an error status code.
When the error occurs in the HTTP Request it is intercepted and invokes the catchError . Inside the catchError you can handle the error and then use throwError to throw it to the service. We then register the Interceptor in the Providers array of the root module using the injection token HTTP_INTERCEPTORS .
I had the same issue of the catchError
function being completely ignored. Since this simple and straightforward code used by @SeaBiscuit as described in the official Angular documentation did not work, I abandoned that approach to handling error responses and instead looked at HttpInterceptors. And that worked!
I was inspired by the guidance of Luuk Gruijs in his article Global HTTP error catching in Angular 4.3+ to add the ErrorInterceptor
shown below to my code.
Admittedly, the interceptor below may not be a perfect, but the most important part for handling errors in interceptors boils down to this:
next.handle(request).pipe(tap(
(event: HttpEvent<any>) => { },
(error: any) => {
// Handle errors here!
}
))
Here's a more detailed glimpse at what I implemented:
export class ErrorInterceptor implements HttpInterceptor {
constructor() { }
intercept (request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (request.method !== 'GET') {
return next.handle(request);
}
const subject = new AsyncSubject<HttpEvent<any>>();
next.handle(request)
.pipe(
tap((event: HttpEvent<any>) => {
// Let HttpResponses pass through interceptor without interaction
if (event instanceof HttpResponse) {
subject.next(event);
subject.complete();
}
}, (error: any) => {
if (error instanceof HttpErrorResponse) {
const errorEvent = new HttpResponse({
body: {
message: error.error.message,
status: error.status,
statusText: error.statusText
}
});
subject.next(errorEvent);
subject.complete();
}
})
).subscribe();
return subject;
}
}
I also modified my service to accept that manually created response body:
return this.http.get<MyObjI | ErrorI>(url, {params});
... where ErrorI
is:
export interface ErrorI {
message: string;
status: number;
statusText: string;
}
Hopefully handling errors in an interceptor does the trick for you, too!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With