NestJS Middleware and Interceptors

NestJS Middleware and Interceptors

Learn about NestJS Middleware and Interceptors with detailed examples and real-world use cases. Discover how to manage request-response cycles, transform data, and handle logging and error management in NestJS applications. Get essential interview questions and insights into how companies use these concepts in development.

When building web applications, it’s important to manage how data flows through the system, and how requests and responses are handled. Imagine that you’re hosting a big party and people are coming to the door. You need someone to check who’s at the door before they enter the party and also make sure they are following the party rules, right? In web development, this is what Middleware and Interceptors do – they act like the doormen for your web application.

In this blog post, we will explain Middleware and Interceptors in NestJS (a popular framework for building server-side applications with Node.js) in a way that’s easy to understand, and we’ll also include examples and interview questions you might face when discussing these topics.


What is NestJS?

Before we dive into Middleware and Interceptors, let’s quickly understand what NestJS is. NestJS is a powerful framework used to build server-side applications with JavaScript and TypeScript. It’s like a set of building blocks that helps developers create APIs and web services easily and effectively.

Think of it like a toy set where all the pieces (tools) fit perfectly together, making it easier to build your toy (application). NestJS works with Node.js, which is like the engine of the toy, making sure everything runs smoothly.


What is Middleware?

Let’s think of Middleware as a “helper” that sits between the moment a request enters your application and the time it reaches its destination (like the controller in a web app). In other words, middleware is a function that runs before the actual request reaches the main part of your application, and it can modify the request, log information, or even block it from going further if needed.

Real-World Example of Middleware:

Imagine you’re at a concert. There’s a person at the entrance (middleware) who checks your ticket before you go inside. If the ticket is valid, you’re allowed to enter; if not, you’re sent back to buy another one. Similarly, middleware checks requests before they proceed to the next part of your application.

How Does Middleware Work in NestJS?

In NestJS, middleware can be added globally (for every request) or on specific routes. The middleware has access to both the request and the response, so it can perform actions like logging, authentication, or modifying data.

Here’s an example of a simple middleware in NestJS:

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => void) {
console.log(`Request... ${req.method} ${req.url}`);
next(); // Make sure to call next() so the request moves on to the next step
}
}

This LoggerMiddleware will log every request that comes into the application, displaying the HTTP method (like GET or POST) and the URL being accessed.

To use this middleware in NestJS, you can apply it globally or for specific routes. Here’s how to apply it globally:

import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';
import { LoggerMiddleware } from './logger.middleware';

@Module({
// your other modules here
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes('*');
}
}

This tells NestJS to use the LoggerMiddleware for all incoming routes.


What are Interceptors?

Now, let’s talk about Interceptors. If Middleware is like the doorman checking who enters the party, then Interceptors are like the event organizers who decide what happens once the guests are inside the party.

In technical terms, Interceptors in NestJS are functions that allow you to intercept (or “wrap”) the request-response cycle. They can perform actions before a request is handled by a route handler, as well as modify the response sent back to the client.

Real-World Example of Interceptors:

Imagine you’re in a restaurant and after eating, the waiter (interceptor) brings you a dessert if you’ve ordered one. Before the food reaches your table (response), the waiter checks if you should get a dessert and adds it to your order if needed. Interceptors modify the response based on certain conditions.

How Do Interceptors Work in NestJS?

Interceptors are functions that can be used to:

  • Transform the result returned by a route handler before sending it to the client.
  • Extend the request-response cycle, allowing you to add custom logic.
  • Log request timings or performance metrics.
  • Catch errors in one central place.

Here’s an example of a simple logging interceptor in NestJS:

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

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before the request is handled');
const now = Date.now();
return next
.handle()
.pipe(
tap(() => console.log(`After the request is handled in ${Date.now() - now}ms`)),
);
}
}

This LoggingInterceptor logs the time it took to handle a request. It works by intercepting the request before it reaches the route handler and logging the time when the response is sent back to the client.

To use this interceptor globally:

import { Module, NestModule, MiddlewareConsumer, APP_INTERCEPTOR } from '@nestjs/common';
import { LoggingInterceptor } from './logging.interceptor';

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

With this, every request and response will be logged, showing the time taken to handle the request.


Middleware vs Interceptors

To make things clearer, let’s compare Middleware and Interceptors:

  • Middleware: Works before a request reaches the route handler and is used to modify the request (e.g., logging, authentication).
  • Interceptors: Work after the request has been handled by the route handler and are used to modify the response or handle post-processing tasks (e.g., transforming data, logging request duration).

Interview Questions on Middleware and Interceptors

If you’re preparing for an interview and these topics come up, here are some questions you might be asked:

  1. What is the difference between middleware and interceptors in NestJS?
    • This is a fundamental question to test your understanding of both concepts.
  2. How can you apply middleware globally and to specific routes in NestJS?
    • Be ready to explain how middleware is applied and demonstrate different usage scenarios.
  3. What are the use cases for interceptors in NestJS?
    • You should explain the benefits of interceptors, such as logging, data transformation, and performance monitoring.
  4. Can you use both middleware and interceptors in the same NestJS project?
    • Yes! Explain that you can use both, as they serve different purposes in the request-response cycle.
  5. How do you handle error handling in middleware and interceptors?
    • You might be asked how you can handle exceptions or modify responses using middleware and interceptors.

Companies That Have Asked About Middleware and Interceptors in Interviews

Several companies have asked about Middleware and Interceptors during interviews for positions involving backend development with NestJS or Node.js. These companies include:

  1. TCS (Tata Consultancy Services)
  2. Wipro
  3. Accenture
  4. Cognizant
  5. Infosys
  6. Capgemini
  7. Zalando
  8. UBS

These companies often value knowledge of how to manage the request-response cycle, log and monitor application behavior, and transform data efficiently.


Conclusion

In conclusion, Middleware and Interceptors are powerful tools in NestJS that help manage and modify the flow of requests and responses in your application. Middleware acts like a doorman, managing the entry of requests into your system, while interceptors act like event organizers, modifying the response before it reaches the client. Both are essential tools for building robust, efficient, and maintainable applications.

By understanding these concepts, you can manage and improve your application’s behavior, making it more scalable and easier to maintain. Don’t forget to prepare for interviews by understanding when and how to use middleware and interceptors in real-world applications!

Interested in learning more about Microservices and NestJS? Check out our latest blogs for more in-depth guides, tutorials, and best practices on building scalable applications with NestJS and microservices.

Leave a Reply

Your email address will not be published. Required fields are marked *