How to build a HTTP Interceptor in Angular 5

Introduction

A HTTP Interceptor enables you to catch HTTP requests and responses so that you can modify them. It is very useful especially when you want to add extra headers to all outgoing requests or catch error responses from the server.

One use case scenario for an interceptor is adding authorization header for authentication to all request. You could add an authorization header manually to all requests but that would be a lot of work. Or you could automatically intercept and append the header before sending the request to the server.

Another use case scenario is handling errors and caching of content. You can use an interceptor to catch errors and log them or serve cached content to the user instead of getting content from the server.

We are going to build a simple Interceptor that will catch-all outgoing requests and incoming responses and log them in console. You can view the console of your browser by opening the developers’ tools.

Getting Started

First, we are going to create a new Angular 5 Application using Angular CLI.

ng new httpinterceptor

A new directory will be created known as httpinterceptor. This is the location of your newly created project. You can run the application and the output would look like this:

How to build a HTTP Interceptor in Angular 5

We shall use JSON PlaceHolder as our endpoint to make our http requests. This is a Fake Online REST API for Testing and Prototyping. It has several variations of http requests which we can call expecting different results, it’s also free.

To make any http requests we need to import the HttpClientModule into our application in the app.module.ts.

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

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

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Next, we need to add two buttons in our app.component.html file. The two buttons will call different methods on click. The first method will call an genuine URL while the second one will call a bogus URL that doesn’t exist hence triggering an error. Replace everything in the file with the following:

<div style="text-align:center">
<h1>
Click one of the two buttons
</h1>
<button (click)="method1Call()">Method 1</button>
<button (click)="method2Call()">Method 1</button>
</div>

Now that we have a user interface, we need to add the two methods to our app.component.ts and import HTTPClient.

import { Component } from '@angular/core';
import { HttpClient } from "@angular/common/http";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {

  title = 'app';
  constructor(private httpClient: HttpClient) { }

  method1Call(): void {
    this.httpClient.get("https://jsonplaceholder.typicode.com/users").subscribe(
      success => {
        console.log("Successfully Completed");
        console.log(success);
      }
    );
  }

  method2Call(): void {
    this.httpClient.get("https://jsonplaceholder.typicode.com/user12").subscribe(
      success => {
        console.log("Successfully Completed");
        console.log(success);
      }
    );
  }
}

We expect the first request to succeed but the 2nd one to fail. Instead of using the fail method inside a subscribe method, we will use the interceptor to catch the errors and log them. Here are the results so far.

How to build a HTTP Interceptor in Angular 5

Adding a HTTP Interceptor

To add an interceptor, create a new class using Angular CLI.

ng g class my-http-interceptor

And then import the following modules (HttpEvent, HttpInterceptor, HttpHandler, HttpRequest

nse) from HTTPClientModule. Then create an interceptor method as follows:

import { Injectable, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/observable/throw'
import 'rxjs/add/operator/catch';


@Injectable()
export class MyHttpInterceptor implements HttpInterceptor {
constructor() { }

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

console.log("intercepted request ... ");

// Clone the request to add the new header.
const authReq = req.clone({ headers: req.headers.set("headerName", "headerValue")});

console.log("Sending request with new header now ...");

//send the newly created request
return next.handle(authReq)
.catch((error, caught) => {
//intercept the respons error and displace it to the console
console.log("Error Occurred");
console.log(error);
//return the error to the method that called it
return Observable.throw(error);
}) as any;
}
}

Now you have an interceptor but it won’t work because the application doesn’t know it exists. Open the app.modules.ts and modify it to include the interceptor by: Importing the interceptor class from your class and import the HTTP_INTERCEPTORS from @angular/common/http as shown below.

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { MyHttpInterceptor } from './httpinterceptor'

Then add a new HTTP_INTERCEPTOR provider to your app.modules.ts. This will enable your app to recognize and use the new interceptor. This should be added inside the @NgModules below the imports as illustrated below:

providers: [
{ 
    provide: HTTP_INTERCEPTORS, 
    useClass: MyHttpInterceptor, 
    multi: true 
} 
],

Your new app.modules.ts should look like this now:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { MyHttpInterceptor } from './httpinterceptor'
import { AppComponent } from './app.component';

@NgModule({
declarations: [
  AppComponent,
],
imports: [
  BrowserModule,
  HttpClientModule
],
providers: [
{
  provide: HTTP_INTERCEPTORS,
  useClass: MyHttpInterceptor,
  multi: true
}
],
bootstrap: [AppComponent]
})

export class AppModule { }

And the results will look as follows for a working interceptor:

How to build a HTTP Interceptor in Angular 5

Method 1 : No Error, Success Message is logged in console

How to build a HTTP Interceptor in Angular 5

When Method 2: It results to an error which is logged inside console

Any new http request you make from this project will all pass through the interceptor. You can view the whole source code of this project on Github here. Thank you.

10 Replies to “How to build a HTTP Interceptor in Angular 5”

  1. This does not seem to work with http … I am using http from ‘@angular/http’ instead of the HttpClient from ‘@angular/common/http’ in my service..Nothing logged in the authInterceptor class shows in my browser console

    1. This is because a httpinterceptor is only supported under HttpClientModule and not the old deprecated HttpModule. The old http module was completely dropped of in Angular 5 and Above and is not recommended for use in Angular 4 and above. In order to use this method, you have to be using the newer HttpClientModule and not HttpModule.

  2. thanks for the nice post.
    i am trying to build the above using AOT, and for some reasons it doesn’t work. Interceptor is not getting invoked when the http call is made. If i make normal JIT build it all works find. Any thoughts ?

    1. I would have to have a look at your http interceptor in order to help you. Would you mind sharing the HTTP Interceptor Class?

  3. How do you make a http call (get put post) in the interceptor function on some condition and get it subscribed here for results inside the interceptor?

    PROBLEM:
    When I inject a class with default constructor it works.
    But when I try to inject a class with parameterised constructor that takes Http like below.

    myservice.ts;
    constructor(private httpClient : Http){} //run time error errorDetails: ‘cannot find all parameters.’

    constructor(){} // no errors

    So how can I use my service inside Interceptor class. Your help will be really appreciated. Thanks

    1. Can you please share your whole interceptor class? I also notice you are injecting Http instead of HttpClient?

      One suggestion I would like to make is using Injector to get the Http service into your interceptor. Something like:

      constructor(private inj: Injector)

      Then in one of your methods :

      let httpClient = this.inj.get(HttpClient);

      1. Thanks! I didn’t know you could inject the injector itself. This solves my ‘cyclic referencing’ error.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.