HTTP interceptors in Angular
Angular
Mahesh Kumawat  

Understanding HTTP Interceptors in Angular: A Complete Guide with 2 Dynamic Use Cases

HTTP interceptors in Angular are a powerful feature in Angular that allows you to intercept and manipulate HTTP requests or responses globally. They provide a centralized place to handle common concerns like authentication, logging, error handling, or modifying request/response data before it reaches your components. By using interceptors, you can ensure that your HTTP calls are consistent and reusable throughout your Angular application.

In this blog, we’ll explain what HTTP interceptors in Angular are, how to use them dynamically, and how to pass custom flags to modify the request or response. We’ll also explore different scenarios and provide clear examples to show how you can leverage this powerful feature in Angular.

What is an HTTP Interceptor in Angular?

An HTTP Interceptor in Angular is a service that implements the HttpInterceptor interface. It allows you to hook into the HTTP request/response pipeline to modify outgoing requests or incoming responses.

An interceptor can:

  • Modify the request before it is sent to the server (for example, adding authentication tokens).
  • Handle or transform the response data before it reaches your components.
  • Catch errors in HTTP responses and handle them globally.

How to Create an HTTP Interceptor in Angular?

To create an HTTP interceptor in Angular, you need to:

  1. Create a service that implements HttpInterceptor.
  2. Implement the intercept() method, which receives two arguments:
    • HttpRequest (the outgoing request)
    • HttpHandler (the handler to send the request through the HTTP pipeline).
  3. Use the HttpHandler.handle() method to send the request to the next interceptor in the chain or the server.

Here’s a basic example of a simple HTTP interceptor that adds an authentication token to every request:

// auth-interceptor.service.ts

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

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Retrieve the authentication token (could be from localStorage or a service)
    const authToken = localStorage.getItem('auth_token');

    // Clone the request and add the Authorization header
    const clonedRequest = req.clone({
      setHeaders: {
        Authorization: `Bearer ${authToken}`
      }
    });

    // Pass the modified request to the next handler in the HTTP chain
    return next.handle(clonedRequest);
  }
}

To register this interceptor in your application, add it to the providers array in your module:

// app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AppComponent } from './app.component';
import { AuthInterceptor } from './auth-interceptor.service';

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

How to Use HTTP Interceptors in Angular Dynamically?

Angular provides a way to inject dynamic values into interceptors. You can pass custom flags or configurations to change the behavior of your interceptors on a per-request basis.

You can achieve this in a couple of ways:

  1. Using Request Headers: You can pass custom flags through HTTP request headers.
  2. Using Request Context: Angular supports passing additional context to HTTP requests which can be accessed in interceptors.

Let’s dive into each scenario and explain how you can achieve this with examples.

1. Passing Custom Flags via Request Headers

You can dynamically pass custom flags through HTTP headers. In the interceptor, you can check for these headers and modify the request or response accordingly.

For example, let’s say you want to add a flag useCustomHeader to requests that should use a custom header. You can implement the interceptor like this:

// custom-header-interceptor.service.ts

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

@Injectable()
export class CustomHeaderInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Check if the custom flag 'useCustomHeader' is present in the request headers
    const customFlag = req.headers.get('useCustomHeader');
    
    // If custom flag is present, modify the request
    if (customFlag) {
      const clonedRequest = req.clone({
        setHeaders: {
          'X-Custom-Flag': 'true'
        }
      });

      // Continue with the modified request
      return next.handle(clonedRequest);
    }

    // Proceed with the original request if the flag is not set
    return next.handle(req);
  }
}

You can now use this interceptor when making HTTP requests:

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

// In your component or service
constructor(private http: HttpClient) {}

makeRequestWithCustomFlag() {
  const headers = { 'useCustomHeader': 'true' };
  
  this.http.get('https://api.example.com/data', { headers })
    .subscribe(response => {
      console.log(response);
    });
}

2. Using Request Context to Pass Dynamic Values

Another way to pass dynamic values is to use request context, which Angular introduced in version 13. This allows you to pass arbitrary metadata along with a request.

Here’s an example of how to achieve this:

// dynamic-context-interceptor.service.ts

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

// Define a context token for dynamic flags
export const CUSTOM_FLAG = new HttpContext();

@Injectable()
export class DynamicContextInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Check if the custom flag exists in the request context
    const customFlag = req.context.get(CUSTOM_FLAG);

    if (customFlag) {
      // Modify the request if the flag is true
      const clonedRequest = req.clone({
        setHeaders: {
          'X-Flag-Context': 'true'
        }
      });

      return next.handle(clonedRequest);
    }

    return next.handle(req);
  }
}

To pass the custom context when making a request, use the setContext() method:

import { HttpClient, HttpContext } from '@angular/common/http';
import { CUSTOM_FLAG } from './dynamic-context-interceptor.service';

// In your component or service
constructor(private http: HttpClient) {}

makeRequestWithContextFlag() {
  const context = new HttpContext().set(CUSTOM_FLAG, true);
  
  this.http.get('https://api.example.com/data', { context })
    .subscribe(response => {
      console.log(response);
    });
}

Conclusion

HTTP interceptors in Angular are a powerful tool for managing HTTP requests and responses in Angular. They can be used for a variety of tasks, including authentication, logging, and error handling. By using dynamic flags in your interceptors, you can customize the behavior of requests on the fly.

  • Custom Headers: A quick and easy way to pass flags dynamically.
  • Request Context: A more flexible approach for passing dynamic flags or data to HTTP requests.

This approach allows you to have full control over your HTTP traffic, making it easier to implement features like custom headers, token management, and more without modifying each individual request.

By integrating HTTP interceptors in Angular patterns in your Angular application, you can centralize your logic for API calls, streamline maintenance, and improve overall consistency across your app.

HTTP interceptors in Angular are very powerful to use, customise the request and response based on needs.

Also read: 10 Tips on JavaScript Performance Optimization

1 Comment

  1. […] Also Read: Angular Must Use Feature: Angular Interceptors […]

Leave A Comment