Have you ever been in need of a centralized system that takes care of your http responses? I am sure that every time you work in a big project with a ton of http requests, that problem comes to the surface.

In this article I will show you how to deal with it, by using an http interceptor and the ngx-toastr plugin to display those messages.

Making an HttpInterceptor work is very simple and requires two steps:

Create a class that implements HttpInterceptor interface Provide the interceptor

Let’s start!

HttpInterceptor

HttpInterceptor is an interface that can be implemented by a class and it has only one method that intercepts an outgoing HttpRequest and optionally transform it or the response. That method called intercept.

intercept method takes two parameters: req (a HttpRequest ) and next (a HttpHandler ) and returns an Observable

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

Typically an interceptor will transform the outgoing request before returning next.handle(req) . An interceptor may choose to transform the response event stream as well, by applying additional Rx operators on the stream returned by next.handle() .

return next.handle(req).pipe(

tap(evt => {}),

catchError(error => {})

);

In this article I will show you how you can handle success and error responses. In case that our http request succeeded, we want to display a toast success message. On the other hand, when the http request returns an error then we will display an error message via toast.

Before we start building our interceptor, we have to import all necessary methods, classes, services and inject the ToastrService in the constructor.

import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse, HttpErrorResponse } from '@angular/common/http'; import { Injectable } from "@angular/core" import { Observable, of } from "rxjs"; import { ToastrService } from 'ngx-toastr';

... constructor(public toasterService: ToastrService) {}

Lets handle success messages first. In order to do this, we must be certain that the evt is an instance of HttpResponse

In my example, I have set my API to return a success property in the response, that contains a message and a title. These are the data I want to display on the toast. Having that said, in that point we will check if this response has a body that contains this success property. Then we will display the success toast that takes three parameters: message, title, additional options. (You can check all the available options here)

tap(evt => {

if (evt instanceof HttpResponse) {

if(evt.body && evt.body.success)

this.toasterService.success(evt.body.success.message, evt.body.success.title, { positionClass: 'toast-bottom-center' });

}

}),

I have also set my API to return an error property in the response when an error occurred that also contains a message and a title. As previously mentioned, we will check if err is an instance of HttpErrorResponse

As you see below, I don’t make any check if this property exists, but I use try/catch expressions to display the custom error or a general one.

catchError((err: any) => {

if(err instanceof HttpErrorResponse) {

try {

this.toasterService.error(err.error.message, err.error.title, { positionClass: 'toast-bottom-center' });

} catch(e) {

this.toasterService.error('An error occurred', '', { positionClass: 'toast-bottom-center' });

}

}

return of(err);

}));

An alternative use of the interceptor will be to log the errors instead of displaying them. Or doing both. Depends on the project.

Putting them all together, that’s our final class. Save it as http.interceptor.ts in your app folder.

import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse, HttpErrorResponse } from '@angular/common/http';

import { Injectable } from "@angular/core"

import { Observable, of } from "rxjs";

import { tap, catchError } from "rxjs/operators";

import { ToastrService } from 'ngx-toastr';

export class AppHttpInterceptor implements HttpInterceptor {

constructor(public toasterService: ToastrService) {} @Injectable ()export class AppHttpInterceptor implements HttpInterceptor {constructor(public toasterService: ToastrService) {} intercept(

req: HttpRequest<any>,

next: HttpHandler

): Observable<HttpEvent<any>> {



return next.handle(req).pipe(

tap(evt => {

if (evt instanceof HttpResponse) {

if(evt.body && evt.body.success)

this.toasterService.success(evt.body.success.message, evt.body.success.title, { positionClass: 'toast-bottom-center' });

}

}),

catchError((err: any) => {

if(err instanceof HttpErrorResponse) {

try {

this.toasterService.error(err.error.message, err.error.title, { positionClass: 'toast-bottom-center' });

} catch(e) {

this.toasterService.error('An error occurred', '', { positionClass: 'toast-bottom-center' });

}

//log error

}

return of(err);

}));



}



}

Provide the interceptor

This is extremely simple! Open your app.module.ts file, go to the providers section and add the following code in the array.

{ provide: HTTP_INTERCEPTORS, useClass: AppHttpInterceptor, multi: true }

You must also import HTTP_INTERCEPTORS and your AppHttpInterceptor

import { ..., HTTP_INTERCEPTORS } from '@angular/common/http'; import { AppHttpInterceptor } from './http.interceptor';

That’s it! Thank you for reading!