Interceptors — Concept for manipulating request and response

Pravin Lolage
Pravin Lolage
Published in
3 min readMay 19, 2020

Let’s take a real-world example of a Water Filter. The use of a water filter is to remove impurities from the water and make it drinkable. In short, it is doing some logic behind to clear the water impurities, so that clean water can be used for drinking.

Does this mean we should use a water filter for non-drinkable water as well? Precisely, not! It completely depends on what we are going to do with filtered water. That is the context of the water. Similarly, interceptors are a mechanism to do some pre-processing or post-processing with your application requests and responses, depending on what you wanted to do with your request or response.

What does mean pre-processing or post-processing?

Suppose you have an application, which has an authentication mechanism. That means whatever requests you received in your application, you verify whether a valid access token is provided, if not you will throw an error with code 403. In simple words, you are pre-processing your requests before calling actual resources.

Now in the same application, when the access token is valid and the resource part is executed, but before sending it, your intention is to write a response to the logger. Basically this is post-processing the request.

So what is the problem? There is no problem at all, in both cases, we can do this job without the Interceptors. But just think logically, for that you need to add the piece of code in every route of request. Here comes the Interceptor design pattern to save your few lines of code and remove redundancy from code.

How does interceptor work?

Where can we use an Interceptor Pattern?

  • bind an extra logic before/after the method execution
  • transform the result returned from a function
  • transform the exception thrown from a function
  • extend the basic function behavior
  • completely override a function depending on specific conditions (e.g., for caching purposes)

Example

Taking an example of NestJs framework — A progressive Node.js framework for building efficient, reliable, and scalable server-side applications. You can write NodeJs in Typescript and the huge benefits of using Typescript like OOPs, linting etc.

Interceptor for logger

In this code, you can see we are getting *context* which holds request and response objects. Once you got the request and response you can log it or send it to tools like newrelic or similar.

Now let’s see how can use this, we can use it in three ways(as depends on the specific framework)

  • For a specific route
  • Globally to handle all requests
  • For a specific module

let see how to add interceptor for a specific route in location.controller.ts

@UseInterceptors(new LoggerInterceptor())
export class LocationController {}

For globally, NestJs supports useGlobalInterceptors() method in main.ts which is an entry file.

const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new LoggerInterceptor());

For a specific module, e.g. in app.module.ts

import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';

@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: LoggerInterceptor,
},
],
})
export class AppModule {}

As listed in the use cases above, it can be used in many places. Feel free to use it.

That's all!!!

Thanks for reading!

If you like the above article please clap the same and if you don’t like please put your thoughts in comments so that I can improve it.

You can reach me out on Linkedin, Quora.

--

--

Pravin Lolage
Pravin Lolage

A software enthusiast with almost 8+ years of experience in programming trying to share my knowledge.