Angular Functional Interceptors using HttpInterceptorFn

By Arvind Rai, January 29, 2024
On this page, we will learn to create functional HTTP interceptors using HttpInterceptorFn in our Angular standalone application. HTTP interceptors are created using HttpInterceptorFn and HttpInterceptor. The withInterceptors() and withInterceptorsFromDi() are passed to provideHttpClient() to configure interceptors.
HttpInterceptorFn : Creates functional interceptor for HTTP requests made via HttpClient.
HttpInterceptor : Creates class based interceptors.
provideHttpClient() : Configures HttpClient to be available for injection.
withInterceptors() : Adds one or more functional interceptors for HttpClient instance.
withInterceptorsFromDi() : Adds one or more class based interceptors.

Here on this page we will learn to create and configure interceptors using HttpInterceptorFn.

1. HttpInterceptorFn

HttpInterceptorFn is a middleware function used to create interceptors. HttpClient calls these interceptors when HTTP requests are made. These interceptors can modify outgoing request or any response that comes back. They can also block, redirect the request and response as well as can change their semantics.
Find the HttpInterceptorFn construct from the Angular doc.
type HttpInterceptorFn = 
 (req: HttpRequest<unknown>, next: HttpHandlerFn) => Observable<HttpEvent<unknown>>; 
req : Request as HttpRequest to hit.
next : Represents the next interceptor as HttpHandlerFn in an interceptor chain.
Now find the simple interceptor that is doing nothing.
import { HttpHandlerFn, HttpInterceptorFn, HttpRequest } from "@angular/common/http";

export const noopInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn) => {
    console.log("-- noopInterceptor --");
    return next(req);
}; 
These interceptors are applied to HttpClient instance. In Angular standalone application, HttpClient is provided using provideHttpClient() and interceptors are configured using withInterceptors() as below.
bootstrapApplication(AppComponent, {
  providers: [
    provideHttpClient(withInterceptors([noopInterceptor]))
  ]
}); 
withInterceptors() accepts array of functional interceptors and they will execute in the order they have been configured.
We can also write functional interface inline with withInterceptors() as below.
providers: [
    provideHttpClient(withInterceptors([
      (req: HttpRequest<unknown>, next: HttpHandlerFn) => {
        console.log("-- noopInterceptor --");
        return next(req);
      }
    ]))
] 

2. Creating Functional Interceptors

We have already learnt creating simple functional interceptor and configure them with withInterceptors(). Here I will create HTTP interceptors for authentication and logging and then will configure them with withInterceptors().
Step-1 :
a. Find the functional interceptor for authentication.
auth-interceptor.ts
import { HttpRequest, HttpInterceptorFn, HttpHandlerFn } from '@angular/common/http';

export const authInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn) => {
    console.log("-- authInterceptor --");
    const authToken = 'AUTH_TOKEN';
    const modifiedReq = req.clone({
        headers: req.headers.set('Authorization', `Bearer ${authToken}`),
    });
    console.log(modifiedReq.headers.get('Authorization'));
    return next(modifiedReq);
}; 
b. Find the functional interceptor for logging.
logging-interceptor.ts
import { HttpRequest, HttpResponse, HttpInterceptorFn, HttpHandlerFn } from '@angular/common/http';
import { tap } from 'rxjs/operators';

export const loggingInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn) => {
  console.log("-- loggingInterceptor --");
  let isSuccess = "";
  return next(req).pipe(
    tap({
      next: event => {
        if (event instanceof HttpResponse) {
          isSuccess = "success";
        }
      },
      error: () => isSuccess = "fail",
      finalize: () => console.log("Request ", isSuccess)
    })
  );
} 
Step-2 : Functional interceptors are passed to withInterceptors() as an array. To configure multiple interceptors, we need to take care their order in array because they will execute in that order.
src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { loggingInterceptor } from './http-interceptors/logging-interceptor';
import { authInterceptor } from './http-interceptors/auth-interceptor';

export const APP_CONFIG: ApplicationConfig = {
  providers: [
    provideHttpClient(withInterceptors([authInterceptor, loggingInterceptor])),
  ]
}; 
In the above code, authInterceptor is at zero index, hence it will execute before loggingInterceptor. The output in console will be as below.
-- authInterceptor --
Bearer AUTH_TOKEN
-- loggingInterceptor --
Request  success 
Configure APP_CONFIG in main.ts.
src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { APP_CONFIG } from './app/app.config';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, APP_CONFIG)
  .catch((err) => console.error(err)); 

3. Reference

4. Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI







©2024 concretepage.com | Privacy Policy | Contact Us