HTTP Interceptors In Angular

HTTP Interceptors In Angular

In this article, we will learn about the HTTP Interceptors in Angular. Along with the new HTTPClientModule, the Angular HTTP Interceptor is introduced. By intercepting the HTTP Request before it is sent to the back end, the Interceptor allows us to change it. The Interceptor can be used to add custom headers to incoming requests, log incoming responses, and so on. Using a few examples, this article demonstrates how to use an Angular HTTP interceptor.

What is an angular HTTP Interceptor?

Our application and the backend are separated by the Angular HTTP interceptors. The interceptor intercepts a request made by the application before it is transmitted to the backend. We will gain access to request headers and bodies by intercepting requests. This allows us to modify the request before it is sent to the server.

The Interceptors can alter the response from the back end before providing it to our application.

The ability to add the Authorization Header to every request is one of the key advantages of the HTTP Interceptors. We could do it manually, but it would be time-consuming and error-prone. Another advantage is that the request's faults are caught and logged.

How to Create HTTP Interceptor

Create an injectable service that implements the HttpInterceptor interface to implement the Interceptor.

@Injectable() export class AppHttpInterceptor implements HttpInterceptor {

The method Intercept must be implemented by this class.

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    //do whatever you want with the HttpRequest
    return next.handle(req);
}

The HTTP_INTERCEPTORS token is then used to give this class in the Root Module:

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

HttpInterceptor Interface

The HttpInterceptor Interface is at the heart of the Interceptor. It's something we'll have to implement in our Interceptor Service.

There is only one method in the interface. Intercept with the signature below.

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

HttpRequest

HttpRequest is the first argument.

An outgoing HTTP request is intercepted with the HttpRequest. It specifies the URL, method, headers, body, and other request parameters.

The HttpRequest class is immutable. This means we won't be able to change the initial request. To make changes, we'll use the HttpRequest to clone the original request. method of cloning

HttpHandler

httpHandler is the second argument.

Using the method HttpHandler.handle, the HttpHandler sends the HttpRequest to the next Handler. Another Interceptor in the chain or the HTTP Backend could be the next handler.

HTTP Interceptor Example

We use a previous article we created project. The final code may be found in the HttpInterceptors folder. The HttpGetParameters folder contains the starting code.

Create the Interceptor

Copy the following code into AppHttpInterceptor.ts in the src/app folder.

import {Injectable} from "@angular/core";
import {HttpEvent, HttpHandler, HttpInterceptor,HttpRequest} from "@angular/common/http";
import {Observable} from "rxjs/Observable";
 
@Injectable()
export class AppHttpInterceptor implements HttpInterceptor {
    constructor() {
    }
 
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        console.log(req);
        return next.handle(req);
    }
}

Let's take a closer look at each code.

We started by importing the following module.

import {Injectable} from "@angular/core";
import {HttpEvent, HttpHandler, HttpInterceptor,HttpRequest} from "@angular/common/http";
import {Observable} from "rxjs/Observable";

Make an AppHttpInterceptor class that implements the HttpInterceptor Interface.

export class AppHttpInterceptor implements HttpInterceptor {

Create an Intercept method that takes two arguments: HttpRequest and HttpHandler.

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    //Do whatever you want to do with the Request
    console.log(req);
    return next.handle(req);
}

You can change the HttpRequest object in the method body. After that, you may use the HttpRequest object to invoke the HttpHandler.handle method of the HttpHandler. The HttpHandler.handle method delivers the request to the backend server or runs the next interceptor.

Add the following code under the app.module.ts.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule,HTTP_INTERCEPTORS} from '@angular/common/http';
import { FormsModule } from '@angular/forms';
 
import { AppComponent } from './app.component';
 
import { GitHubService } from './github.service';
import {AppHttpInterceptor} from './AppHttpInterceptor';
 
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    FormsModule
  ],
  providers: [GitHubService,
    {
    provide: HTTP_INTERCEPTORS,
    useClass: AppHttpInterceptor,
    multi: true
  }
],
  bootstrap: [AppComponent]
})
export class AppModule { }

We'll start by importing HttpClientModule and HTTP_INTERCEPTORS from @angular/common/http.

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

Then, for the HTTP_INTERCEPTORS, register AppHttpInterceptor as the Provider.

providers: [GitHubService,
  {
  provide: HTTP_INTERCEPTORS,
  useClass: AppHttpInterceptor,
  multi: true
}

Start the application. View the output of the console log in the developer console.log(req).

Setting the new headers

In the case above, we were able to intercept the request and log it to the console. We'll now make changes to the HTTP Headers and Custom Headers.

Adding the Content-Type

We must clone the request in order to modify it. The HttpRequest.clone method allows us to change some of the request's properties while copying others. The new header content-type is added to the request in the following example.

req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });

In addition, the header's object is immutable. As a result, we must clone it using the headers. method to be used The title. The set method duplicates the current header, adds or alters the new header value, and returns the cloned header.

The headers can also be used.

As seen in the example below, the append method is used to add items to a list. Even if the value is already present, the add function always appends the header.

req = req.clone({ headers: req.headers.append('Content-Type', 'application/json') });

You can also use the setHeaders shortcut, which is demonstrated below.
req = req.clone( {setHeaders: {‘Content-Type’: ‘application/json’}} );

You might wish to use headers to see if the header already exists. header.has() is a method that checks if something exists.
if (!req.headers.has('Content-Type')) {
    req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
}

Check the header's current value.

req.headers.get('Accept')

Also, a header should be removed.

req = req.clone({ headers: req.headers.delete('Content-Type','application/json') });

Adding the Authorisation token

Add a token for permission.

const token: string =authService.Token; //Get token from some service
if (token) {
    req = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + token) });
}

Intercepting the Response

The various Rxjs Operators can be used to intercept the back-end server's response. Before delivering the response to the application, the map can be used to change it. The do operator can be used to keep track of events or time requests. To capture the error, use the catch operator. To retry a failed operation, use the retry operator.

Logging 

The use of the do operator is demonstrated in the following example code. When specified events occur on an Observable, the do operator is called.

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

    req = req.clone({ headers: req.headers.append('Content-Type', 'application/json')});
    const started = Date.now();

    return next.handle(req)
    .do(event => {
        console.log(event);
        const elapsed = Date.now() - started;
        console.log(`Request for ${req.urlWithParams} took ${elapsed} ms.`);
        if (event instanceof HttpResponse) {
            console.log(`Response Received`);
        };
    });
}

Do is used twice in the preceding example. When the request is sent to the server for the first time (event=type: 0). When the response is received for the second time (event instanceof HttpResponse).

Modify Response

The map operator, which allows us to transform the response, is demonstrated in the following code. The clone method can be used to change the response (the response object is immutable). The copied response should then be returned. The example below returns the response after replacing the entire response body with the new body.

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

    return next.handle(req)
        .map(resp => {

            const myBody = [{ 'id': '1',
                              'name': 'TekarticlesHub',
                              'html_url': 'www.tekarticleshub.com',
                              'description': 'description' 
                            }];

            // on Response
            if (resp instanceof HttpResponse) {
                console.log(resp);
                console.log(resp.body);
                resp = resp.clone<any>({ body: myBody});
                return resp;
            }
        });
}

Catching the Error

The catch operator can be used to catch errors. The HttpErrorResponse, which represents an error object, is passed to the catch callback as an input. It comprises information such as headers, status, statusText, and URL, among other things.

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
 
        const token: string = 'invald token';
        req = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + token) });
 
        return next.handle(req)
            .map(resp => {
                // on Response
                if (resp instanceof HttpResponse) {
                    // Do whatever you want with the response.
                    return resp;
                }
            }).catch(err => {
                // onError
                console.log(err);
                if (err instanceof HttpErrorResponse) {
                    console.log(err.status);
                    console.log(err.statusText);
                    if (err.status === 401) {
                        // redirect the user to login page
                        // 401 unauthorised user
                    }
                }
                return Observable.of(err);
            });
    }

Cancel the current Request

By returning the EMPTY observable, we can also cancel the current request.

The code below checks to see if the user is logged in. If this is not the case, the request will not be sent to the server.

import { EMPTY } from 'rxjs';
 
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  if (NotLoggedIn) {
    return EMPTY;
  }
 
  return next.handle(request);
}


Change the Requested URL

Before the requested URL is delivered to the server, you can modify it. The url attribute of the HttpRequest can be changed before sending the request.

This comes in handy when you need to add the base URL for all queries, switch from HTTP to HTTPS, and so on.

const baseURL="https://www.tekarticlesHub.com/";
 
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
 
   const newReq = req.clone({
      url: baseURL + req.url;
    });
 
   return next.handle(httpsReq);
}

Conclusion

Using the new HttpClientModule, we learned how to intercept HTTP requests and responses. The Interceptor can be used to add custom headers to incoming requests, log incoming responses, and so on.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in the comment section.

Post a Comment

Previous Post Next Post