Understanding NestJS Middleware: Creating and Applying Middleware to Handle Requests and Responses
- 748Words
- 4Minutes
- 10 Jul, 2024
In NestJS, middleware is a crucial component for handling requests and responses. This article will provide an in-depth understanding of the concept of middleware in NestJS and explain how to create and apply middleware to handle requests and responses.
What is Middleware
In NestJS, middleware is a function that can access the request object (req), response object (res), and the next middleware function in the application’s request-response cycle (next). Middleware can perform various operations before handling the request, such as user authentication, logging, modifying the request object, and more.
The definition and usage of middleware in NestJS are similar to Express.js, but NestJS offers more robust modularity and type safety support.
Creating Middleware
To create middleware, you need to implement the NestMiddleware
interface and define the use
method. Here is a simple example of a logging middleware:
1import { Injectable, NestMiddleware } from "@nestjs/common";2import { Request, Response, NextFunction } from "express";3
4@Injectable()5export class LoggerMiddleware implements NestMiddleware {6 use(req: Request, res: Response, next: NextFunction) {7 console.log(`Request...`);8 next();9 }10}
In the example above, the LoggerMiddleware
will log each request and call the next()
function to pass control to the next middleware or route handler.
Applying Middleware
To apply middleware, you can use the MiddlewareConsumer
in the configure
method of the module. Here is an example of applying the LoggerMiddleware
to all routes:
1import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";2import { LoggerMiddleware } from "./logger.middleware";3
4@Module({5 // other module configurations6})7export class AppModule implements NestModule {8 configure(consumer: MiddlewareConsumer) {9 consumer.apply(LoggerMiddleware).forRoutes("*");10 }11}
The apply
method specifies the middleware to be applied, and the forRoutes
method specifies the scope of the middleware. forRoutes('*')
means the middleware will be applied to all routes.
Middleware Examples
Modifying the Request Object
The following middleware will add a custom property customProperty
to the request object:
1import { Injectable, NestMiddleware } from "@nestjs/common";2import { Request, Response, NextFunction } from "express";3
4@Injectable()5export class CustomPropertyMiddleware implements NestMiddleware {6 use(req: Request, res: Response, next: NextFunction) {7 req["customProperty"] = "Custom Value";8 next();9 }10}
Modifying the Response Object
Here is an example of middleware that modifies the response object:
1import { Injectable, NestMiddleware } from "@nestjs/common";2import { Request, Response, NextFunction } from "express";3
4@Injectable()5export class ResponseModifierMiddleware implements NestMiddleware {6 use(req: Request, res: Response, next: NextFunction) {7 res.on("finish", () => {8 console.log("Response finished");9 });10 next();11 }12}
Multiple Middleware Working Together
Multiple middleware can work together, each performing its own operations. Here is an example using both LoggerMiddleware
and CustomPropertyMiddleware
:
1import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";2import { LoggerMiddleware } from "./logger.middleware";3import { CustomPropertyMiddleware } from "./custom-property.middleware";4
5@Module({6 // other module configurations7})8export class AppModule implements NestModule {9 configure(consumer: MiddlewareConsumer) {10 consumer.apply(LoggerMiddleware, CustomPropertyMiddleware).forRoutes("*");11 }12}
In this example, LoggerMiddleware
logs the request, and CustomPropertyMiddleware
adds a custom property to the request object. All requests will go through both middleware.
Different Usages of forRoutes and exclude
The forRoutes
method can specify middleware to be applied to specific paths, controllers, or methods.
Applying to a Specific Path
1consumer2 .apply(LoggerMiddleware)3 .forRoutes({ path: "cats", method: RequestMethod.GET });
Applying to a Specific Controller
1import { CatsController } from "./cats.controller";2
3consumer.apply(LoggerMiddleware).forRoutes(CatsController);
Applying to Multiple Paths and Methods
1consumer2 .apply(LoggerMiddleware)3 .forRoutes(4 { path: "cats", method: RequestMethod.GET },5 { path: "dogs", method: RequestMethod.POST },6 );
Excluding Specific Paths
The exclude
method is used to exclude specific paths, so middleware does not apply to these paths:
1consumer2 .apply(LoggerMiddleware)3 .exclude(4 { path: "cats", method: RequestMethod.GET },5 { path: "dogs", method: RequestMethod.POST },6 )7 .forRoutes("*");
In this example, LoggerMiddleware
will be applied to all paths except GET /cats
and POST /dogs
.
Functional Middleware
Besides class-based middleware, NestJS also supports creating middleware using functions. Here is an example of functional middleware:
1import { Request, Response, NextFunction } from "express";2
3export function logger(req: Request, res: Response, next: NextFunction) {4 console.log(`Request...`);5 next();6}
When using functional middleware, you do not need to implement the NestMiddleware
interface. You can directly apply it in the module:
1import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";2import { logger } from "./logger.middleware";3
4@Module({5 // other module configurations6})7export class AppModule implements NestModule {8 configure(consumer: MiddlewareConsumer) {9 consumer.apply(logger).forRoutes("*");10 }11}
Conclusion
This article provided an in-depth understanding of the concept of middleware in NestJS and explained how to create and apply middleware to handle requests and responses. By using middleware, developers can perform various operations during request processing, such as authentication, logging, and request modification, enhancing the functionality and security of applications. We also demonstrated examples of multiple middleware working together, modifying request and response objects, and using the forRoutes
and exclude
methods to control the scope of middleware. Additionally, we introduced how to create and apply functional middleware.