Function-Based Interceptor in Angular

Angular interceptors are a great way to handle and modify HTTP requests and responses across your app. While interceptors are usually implemented as classes, you can use function-based interceptors for simpler and more reusable code.

In this blog, we’ll cover how to create and use function-based interceptors in Angular, with easy-to-follow examples for better clarity and flexibility.

The source code can be downloaded from GitHub.

What is a function-based Interceptor?

A function-based interceptor is a simpler and more flexible option compared to a class-based interceptor. Instead of creating a whole class with an intercept method, you put your logic into individual functions. This approach helps with,

  • Separation of Concerns: Smaller, focused functions are easier to test and maintain.
  • Reusability: You can reuse the interceptor logic by sharing or combining multiple functions.

Benefits of Function-Based Interceptors

  • Less Setup: You only need a function, not an entire class.
  • Easier Testing: It’s simpler to test individual functions.
  • Flexible: You can combine several functions to handle complex request/response processes.

How to implement a function-based Interceptor?

  1. Let us create an angular project with the imported HttpClientModule.
    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { HttpClientModule } from '@angular/common/http';
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [AppComponent],
      imports: [BrowserModule, HttpClientModule],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
  2. Create a function-based interceptor - a function-based interceptor works by using a factory to handle the request/response logic.
    import { HttpInterceptorFn } from '@angular/common/http';
    
    export const authInterceptor: HttpInterceptorFn = (req, next) => {
      console.log('Intercepting Request:', req);
    
      // Add an Authorization header
      const token = 'your-token-here';
      const clonedRequest = req.clone({
        setHeaders: {
          Authorization: `Bearer ${token}`,
        },
      });
    
      console.log('Modified Request:', clonedRequest);
    
      // Forward the modified request
      return next(clonedRequest);
    };
    

Key Points

  • Factory Function: Use HttpInterceptorFn to define the interceptor.
  • Modify Request: Use req.clone() to create a modified version of the request.
  • Forward Request: Send the cloned request to the next step with next.

Register the Function Interceptor

To register the function-based interceptor, use the provided HTTP client configuration in your AppModule or feature module.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule, provideHttpClient, withInterceptors } from '@angular/common/http';
import { authInterceptor } from './auth-interceptor.fn';

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

Why Use provideHttpClient?

Introduced in Angular 15, this modern API makes it easier to configure the HTTP client and supports function-based interceptors directly.

Use the Interceptor in an HTTP Request

Now that the interceptor is registered test it by making an HTTP request.

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'function-based-Interceptor';

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    this.http.get('https://jsonplaceholder.typicode.com/posts').subscribe((data) => {
      console.log('Response:', data);
    });
  }
}

Let us execute the app and validate whether the interceptor was properly executed.

Execute App

Interceptor properly invoked.

Interceptor

Benefits of Using Function-Based Interceptors

  • Lightweight: Less extra code to write.
  • Modular: Perfect for small tasks like changing headers or logging.
  • Future-Proof: Works well with modern Angular features like provideHttpClient.

Conclusion

Function-based interceptors offer a simple, organized, and flexible way to manage HTTP requests and responses in Angular apps. Whether you're adding authorization tokens, logging requests, or handling errors, function interceptors make it easier. Use this approach to keep your code clean and ready for the future.

Give it a try in your project today, and enjoy the simplicity of function-based interceptors!

Happy Coding!