Thursday 22 March 2018

Catch all http errors using interceptors – Angular

AngularResponse InterceptorError handlinghttpClient

In this article we are going to discuss about creating a response interceptor using angular. Using this interceptor we can catch all http errors as well as success response in a single place. Since most of the applications will be using token to validate session, it is import to know API error status.

For example if we are getting 404 or 403 error from some API then we might trigger logout or need to indicate users about their session is invalid. We cannot go and check all the http request in all the service files, instead we will create a response interceptor and the same can be used for finding http status.

We can create interceptor to pass a common token to all http request as well. I have explained the same in my previous post. Please note this will work only angular 4.3 version and above.

Read more: - Set token to all htpp request.

Response interceptor


Check below complete code for response interceptor.


import { Injectable } from '@angular/core';
import {
    HttpInterceptor,
    HttpRequest,
    HttpHandler,
    HttpEvent,
    HttpResponse,
    HttpErrorResponse
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';

@Injectable()
export class ResponseInterceptor implements HttpInterceptor {
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        return next.handle(request).do((event: HttpEvent<any>) => {
            if (event instanceof HttpResponse) {
                //success
                console.log('Success');
            }
        },
            (error: any) => {
                if (error instanceof HttpErrorResponse) {
                    if (error.status === 401) {
                        console.log('error found');
                    }
                    if (error.status === 404) {
                        console.log('Not found');
                    }
                    //etc
                }
            }
        )
    }
}

In the success block you will be getting all the success response from the API. If you want to handle some special case after getting result of some particular APIs, you can write those in the response block. In the above example I am checking the error status of http calls as well. Similarly you can add other status as well. We need to add ResponseInterceptor as part of our provider list in Module. Check below updated module code.

Module


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';

// Components
import { AppComponent } from './app.component';

//interceptor
import { ResponseInterceptor } from './interceptor';


@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    RouterModule.forRoot(appRoutes)
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: ResponseInterceptor,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Here we have imported HTTP_INTERCEPTORS. In my previous post post I have explained about creating an interceptor to pass headers to all http calls. One thing to remember we need to use httpClient to make it work. If you want to add more interceptors in the module see below updated code.


providers: [AuthServices,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: SecurityTokenInterceptor,
      multi: true
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: ResponseInterceptor,
      multi: true
    }
  ],

You can create multiple interceptors but you need to mention those in the module.

We can update response interceptor to invoke some methods in another service file. For example after getting 403 error from any of the API you may need to call the logout method in AuthService. Check below updated code.


import { Injectable } from '@angular/core';
import {
    HttpInterceptor,
    HttpRequest,
    HttpHandler,
    HttpEvent,
    HttpResponse,
    HttpErrorResponse
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import { AuthServices } from './services/authServices';

@Injectable()
export class ResponseInterceptor implements HttpInterceptor {

    constructor(public auth: AuthServices) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        return next.handle(request).do((event: HttpEvent<any>) => {
            if (event instanceof HttpResponse) {
                //success
                console.log('Success');
            }
        },
            (error: any) => {
                if (error instanceof HttpErrorResponse) {
                    if (error.status === 401) {
                        this.auth.logout();
                        //any other action
                    }
                    if (error.status === 404) {
                        this.auth.openModelPopUp()
                        //any other action
                    }
                    //etc
                }
            }
        )
    }
}

Here we are calling logout method in the AuthService after getting 403 error. Similar way you can modify this to show a model popup or some other actions. If you want to know more about communicating between service files check this link and there are more ways to communicate with components - 7 method to share data between components. Clubbing these all logics we can implement a better application.

Read more: - Login authentication flow using auth guard.

In this article we have discussed about reading http response using an interceptor.

Angular 4.3(+)Angular 5Response InterceptorError handlinghttpClient

Related Info

1. Get Url parameter using Angular 2/5.

2. Share data between non related components - Angular 2/5.

No comments :

Post a Comment