What is The Difference Between Interceptor, Middleware and Filter in Nest.js?
Last Updated :
12 Aug, 2024
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
What is the difference between find() and filter() methods in JavaScript ? In this article, we will see the difference between the find() and filter() methods in javascript. JavaScript find() method: The find() method is used to find all the descendant elements of the selected element. It finds the element in the DOM tree by traversing through the root to the leaf. Syntax:
2 min read
Difference between app-level and route-level middleware in Express Middleware functions are functions that have access to the request object ( req ), the response object ( res ), and the next middleware function in the application's request-response cycle. In this article, we will go through app-level and route-level middleware and also see the key differences betw
3 min read
What is the difference between export.create and router.post? export.create and router.post are used in the context of backend frameworks like Express JS. They both are used for handling HTTP requests and operate at different levels within the framework. In this article we will learn about export.create and router.post and see the key differences between them.
3 min read
Difference between application level and router level middleware in Express? If youâve used Express even a little, you know how important middleware is. Those little functions run on every request and let you do stuff like logging, authentication, file uploads, and more. In this article, we will see what is Application-level middleware and Router-level middleware and what ar
3 min read
Why Do We need DTOs and interfaces Both in Nest.js? NestJS works as an innovative framework with a TypeScript core that helps developers create stable and adaptable applications. With TypeScript's extensive typing, you get direct access to constructs such as interfaces and Data Transfer Objects (DTOs) in NestJS. However, the times one should use thes
7 min read
What is the role of next(err) in error handling middleware in Express JS? Express is the most popular framework for Node.js which is used to build web-based applications and APIs. In application development, error handling is one of the important concepts that provides the aspect to handle the errors that occur in the middleware. The middleware functions have access to th
4 min read