Open In App

What is The Difference Between Interceptor, Middleware and Filter in Nest.js?

Last Updated : 12 Aug, 2024
Summarize
Comments
Improve
Suggest changes
Share
Like Article
Like
Report

Nest.js is a popular framework for building server-side applications in Node.js. While working with Nest.js, we'll often come across terms like Interceptor, Middleware, and Filter. These are important concepts that help in managing requests, responses, and errors in your application.

What is Middleware?

Middleware in Nest.js is a function that executes before the request reaches your route handler. It can do things like logging requests, checking authentication, or parsing JSON bodies.

Uses of Middleware:

  • Pre-Request Processing: Middleware allows you to process and modify requests before they reach the route handler, such as parsing request bodies, handling authentication, or setting response headers.
  • Centralized Logic: It helps in centralizing common functionality, like logging or authentication, across multiple routes, improving code maintainability.
  • Chaining and Sequencing: Middleware functions can be chained together, allowing complex operations to be split into manageable, sequential steps.
  • Cross-Cutting Concerns: Middleware is ideal for handling cross-cutting concerns like error handling, rate limiting, or input validation, applicable across multiple routes.

How Middleware Works?

  • Middleware functions run before the actual request handler.
  • You can have multiple middleware functions that execute in sequence.
  • Middleware can modify the request object (req), and response object (res), or end the request-response cycle.

Syntax

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

@Injectable()
export class AuthMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
// Check for authentication token
if (req.headers['authorization']) {
// Token exists, proceed
next();
} else {
// No token, respond with error
res.status(403).send('Unauthorized');
}
}
}

What is an Interceptor?

Interceptors in Nest.js are used to transform or modify the data before sending it to the client or before processing it in the handler. They sit between the request and the response, allowing you to perform actions like logging, transforming responses, and handling exceptions.

Uses of Interceptor

  • Response Transformation: Interceptors can modify or transform the data before it is sent back to the client, making them ideal for tasks like formatting or wrapping responses.
  • Pre- and Post-Processing: They allow you to perform actions both before the request is handled by the route and after the response is prepared, giving you control over the request-response lifecycle.
  • Error Handling: Interceptors can catch errors during the processing of a request and handle them appropriately, often used in conjunction with filters.
  • Caching and Performance: They can be used to implement caching strategies or to measure and log performance metrics for requests and responses.

How Interceptors Work?

  • Interceptors can run before the request handler and after the response is created.
  • They can modify the data being sent back to the client.
  • They can catch exceptions and transform error responses.

Syntax -

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

@Injectable()
export class TransformInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map(data => ({
success: true,
data
}))
);
}
}

What is a Filter?

Filters in Nest.js are designed to handle exceptions and errors. When something goes wrong in your application, a filter can catch the error and format the response in a user-friendly way. Filters ensure that the client receives a consistent error message structure.

Uses of Filter

  • Exception Handling: Filters are designed to catch and handle exceptions that occur during request processing.
  • Custom Error Responses: Filters enable you to define custom responses for specific types of errors.
  • Global Error Management: They can be applied globally to handle all exceptions across the application, centralizing error handling logic.
  • Specific Exception Targeting: Filters can be set to handle specific types of exceptions.

How Filters Work?

  • Filters catch errors thrown during the request handling process.
  • They provide a standard format for error responses.
  • You can add custom logic to handle different types of errors.

Syntax -

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpErrorFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const request = ctx.getRequest < Request > ();
const response = ctx.getResponse < Response > ();
const status = exception.getStatus();

response
.status(status)
.json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
message: exception.message
});
}
}

Differences between Interceptor, Middleware and Filter in Nest.js

Aspect

Middleware

Interceptor

Filter

Purpose

Pre-process requests before they reach handlers

Transform data before sending to clients or after processing in handlers

Handle exceptions and errors consistently

Execution Timing

Before the request reaches the route handler

Around the request and response cycle

When an exception is thrown during request processing

Use Cases

Authentication, logging, request parsing

Response transformation, logging, exception handling

Global error handling, custom error responses

Modification Scope

Request (req) and Response (res) objects

Data being sent to or received from handlers

Error responses sent to clients

Number of Instances

Can have multiple middleware functions in sequence

Can have multiple interceptors in sequence

Typically one filter per error type, but can be multiple

Custom Logic

Add custom logic for pre-processing requests

Add custom logic for data transformation and logging

Add custom logic for handling different types of errors

Example Functionality

Check for authentication token

Change structure of the response data

Format error responses in a user-friendly way

Implementation Example

AuthMiddleware for checking tokens

TransformInterceptor for changing response format

HttpErrorFilter for consistent error responses

Conclusion

  • Use Middleware when you need to process or modify requests before they hit your route handlers, especially for logging, authentication, or request validation.
  • Use Interceptors when you need to modify or transform the request or response data or implement logic that should occur both before and after the request is handled.
  • Use Filters when you need to handle exceptions, especially if you want to ensure consistent error handling across your application.

Similar Reads