ScanSkill
Sign up for daily dose of tech articles at your inbox.
Loading

How to Use Interceptors in NestJS

How to Use Interceptors in NestJS
How to Use Interceptors in NestJS

Let’s learn how to use interceptors in NestJS, its integration points, and the difference between interceptors and middleware.

Introduction

Interceptors follow the core concept of Aspect Oriented Programming (AOP). It aims to increase modularity and makes it possible for the separation of concerns. Interceptors are used to bind logic before a request is executed and after the route handler returns the response. Interceptors are used to transform requests and responses.

Interceptor classes implement the NestInterceptor interface. It has access to the intercept() method, it takes the argument ExecutionContext and the CallHandler. The ExecutionContext has access to the request, response, and next object. The CallHandler is used to invoke the route handler method. With the CallHandler you can also access the response data by taping into it.

Let’s look at how the interceptors work in NestJS, from the image below.

The working mechanism of Interceptors in NestJS
The working mechanism of the interceptor

As we can see unlike middleware and guards the working point of interceptors in NestJS is after the route has handled the request and sent the response back to the client.

Prerequisites

Interceptors in NestJS

We have looked at, how Interceptors in NestJS generally function, now let’s look at how it is made and how it is applied globally and in a single route.

Firstly create a nest project.

## Generating a nest project
$ nest new nest-interceptor

## for package manager select according to your choice
## article uses: npm

After your NestJS project is created, open it with your favorite code editor. Now that the project is set up let’s move on to the actual part of creating the interceptor. the guard can simply be created by using the nest CLI.

$ nest g interceptor app --no-spec 

The --no-spec option makes sure that the test classes are not generated.

Generating Interceptor in NestJS
Generating Interceptor in NestJS
The generated Interceptor
The generated Interceptor

Now, let’s edit the interceptor and make it so that the API response body is logged along with the user agent. Let us look at that in actual code, and learn about interceptors in NestJS.

//* app.interceptor.ts

import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable, tap } from 'rxjs';

@Injectable()
export class AppInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const userAgent = context.switchToHttp().getRequest().headers['user-agent'];
    return next.handle().pipe(
      tap(data => {
        console.log(`----------Request start: ${userAgent}----------`)
        console.log(data)
        console.log(`----------Request end: ${userAgent}----------`)
      })
    );
  }
}

The above code will log the response sent back to the client, along with the user-agent of the client.

Now, let’s bind the interceptor in a single route handler which is present in the controllers, which is the / base route.

//* app.controller.ts

import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { AppInterceptor } from './app.interceptor';

@Controller()
export class AppController {

  @Get()
  @UseInterceptors(AppInterceptor)
  getHello(): string {
    return 'Hello !'
  }

  @Get('/no-interceptor')
  getBye(): string {
    return 'Bye !';
  }
}

Route with interceptor

Invoking the route with the interceptor
Invoking the route with the interceptor
Log made by invoking the route

Route without interceptor

Invoking route without the interceptor
Invoking route without the interceptor
No log was made while making a request to route without the interceptor
No log was made while making a request to route without the interceptor

Now, that we have invoked the route containing the logging interceptor, the response body is logged, and the user-agent of the client is also logged. When Invoking a route that does not contain an interceptor is invoked, the logging action does not happen.

Let us look at applying Interceptors in NestJS globally. For applying Interceptors globally we need to apply the guard in the main.ts file, or the starting point of the application. We need to add the code app.useGlobalInterceptors() there to add the interceptor globally, let’s look at the code below.

//* main.ts

import { NestFactory } from '@nestjs/core';
import { AppInterceptor } from './app.interceptor';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalInterceptors(new AppInterceptor())
  await app.listen(3000);
}
bootstrap();

Now let’s test out the /no-interceptor route which was not protected by the guard, previously now it is protected by the global guard.

Route without interceptor after global implementation

Invoking the route without the interceptor
Invoking the route without the interceptor
After global implementation all routes contain the interceptor
After global implementation, all routes contain the interceptor

We can see that, even if the interceptor is not included, the interceptor is still invoked because it is added globally by using the app.useGlobalInterceptors() in the main.ts file.

Difference Between Middleware and Interceptor

Middlewares and Interceptors act similarly, meaning they have access to the request and the response object, and manipulate it. The difference is that middleware can only act on the request that is sent by the client before it hits the route handler. Whereas the interceptor can act before the request is handled by the route handler and also after the response leaves the route handler. The middleware acts on the request part, while the interceptor works on both the request and response part.

Conclusion

In this article, we learned about using interceptors in NestJS. We looked upon a practical example of it, by implementing a logger using an interceptor, and also looked at the difference between middleware and interceptors in NestJS. Like interceptors, there are also guards to learn more about NestJs guards look into our article How To Use Guards in NestJS.

Sign up for daily dose of tech articles at your inbox.
Loading