How to work with HTTP Interceptors in Angular

I have been working in Angular for quite some time now and have worked on almost every version of it. It’s amazing how every version comes with new features. One feature that caught my eye is HttpInterceptor. It was first introduced in Angular 4.3 and it’s pretty useful.

Introduction to Interceptors

Interceptors provide a method to intercept an outgoing request or incoming response. They are very similar to the middleware, with a framework like Express, except for the frontend. Interceptors can be very useful for features like caching and logging.

HttpInterceptor provides a way to intercept HTTP requests and responses to transform or handle them before passing them along.

Basic Implementation

Creating an interceptor is pretty simple. You have to create a class that is @injectable and implements the HttpInterceptor:

@Injectable()
export class ApiInterceptor implements HttpInterceptor {  
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authReq = req.clone({
        //add original request and/or set/add new headers 
    });
});
  return next.handle(authReq);
 }
}

This takes req and next as a parameter and returns HttpEvent as an observable.

After that you need to provide it in the AppModule like this:

@NgModule({
  bootstrap: [AppComponent],
  imports: [...],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: ApiInterceptor,
      multi: true
    }
  ]
})
export class AppModule {}

This is the basic implementation of HttpInterceptor in a pretty simple way.

Why Should You Use HttpInterceptors?

HttpInterceptors can perform a variety of tasks, from authentication to logging, setting or adding headers, HTTP request and response, notifications, error handling, and showing a loader on every HTTP request. Without interceptors, developers would have to add these tasks manually for every HTTP client call.

1. Set headers

We can easily add authorization headers so we don’t have to add them separately in every request:

const addHeaders= req.clone({ 
   headers: req.headers
     .set('Authorization', `Bearer $token`)
     .set('Content-Type', 'application/json')
});
return next.handle(addHeaders);

As you can see, it’s simple to manipulate headers in the interceptor.

2. Show loader

We can add a loader in the interceptor for every request. For this, we add a loader service which has show and hide loader methods. We can then show the loader for every request and hide it when the request is finalised:

const loaderService = this.injector.get(LoaderService);

loaderService.show();

return next.handle(req).pipe(
  delay(5000),
  finalize(() => loaderService.hide())
);

This is a better solution — we don’t have to call the loader service with every single API request.

3. Notifications

We can show a notification every time the response status is 200 or 201, which indicates success.
Here’s an example of object creation:

return next.handle(req).pipe(
  tap((event: HttpEvent<any>) => {
    if (event instanceof HttpResponse && event.status === 201) {
      this.toastr.success("Object created.");
    }
  })
);

This will show the success toaster every time the response status is 201. This is pretty useful as you won’t have to explicitly add toaster in every API request.

4. Error handling

There are multiple cases which can cause an error in interceptor. We can use the retry operator inside the pipe function (which combines multiple functions) for the http request.
We use Retry from RxJS to resubscribe to the observable and in return we get a successful result:

return next.handle(req).pipe(
  retry(2),
  catchError((error: HttpErrorResponse) => {
    if (error.status !== 401) {
      // 401 handled in auth.interceptor
      this.toastr.error(error.message);      
    }
    return throwError(error);
  })
);

We can check the status of error and on that basis we can decide what to do with it.

In the above example we’re using the retry operator before checking the status of the exception. If the status isn’t 401 then we’re throwing a toaster error. So that’s how we will be handling error in interceptor.

With HttpInterceptors, we can do other things too like profiling, URL manipulation and more.

That’s pretty much it.

Thank you for reading. I hope it helps!

#angular

How to work with HTTP Interceptors in Angular
2 Likes13.25 GEEK