深入理解NestJS中間件:創建和應用中間件處理請求與響應
- 1124字
- 6分鐘
- 2024-07-10
在 NestJS 中,中間件(Middleware)是處理請求和響應的重要組件。本文將詳細介紹 NestJS 中間件的概念,並講解如何創建和應用中間件來處理請求和響應。
什麼是中間件
在 NestJS 中,中間件是一個函數,它可以訪問請求對象(req)、響應對象(res)和應用程序請求-響應週期中的下一個中間件函數(next)。中間件可以在處理請求前進行操作,例如驗證用戶身份、記錄日誌、修改請求對象等。
中間件的定義與使用方式類似於 Express.js,但 NestJS 提供了更強大的模塊化和類型安全支持。
創建中間件
要創建一個中間件,需要實現 NestMiddleware
介面並定義 use
方法。以下是一個簡單的日誌記錄中間件示例:
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}
在上面的示例中,LoggerMiddleware
中間件會記錄每個請求並調用 next()
函數將控制權交給下一個中間件或路由處理器。
應用中間件
要應用中間件,可以在模塊的 configure
方法中使用 MiddlewareConsumer
來指定中間件的應用範圍。以下是一個將 LoggerMiddleware
應用於所有路由的示例:
1import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";2import { LoggerMiddleware } from "./logger.middleware";3
4@Module({5 // 其他模塊配置6})7export class AppModule implements NestModule {8 configure(consumer: MiddlewareConsumer) {9 consumer.apply(LoggerMiddleware).forRoutes("*");10 }11}
apply
方法指定要應用的中間件,forRoutes
方法指定中間件的應用範圍。forRoutes('*')
表示將中間件應用於所有路由。
中間件示例
修改請求對象
下面的中間件會添加一個自定義屬性 customProperty
到請求對象中:
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}
修改響應對象
以下是一個修改響應對象的中間件示例:
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}
多個中間件協作
多個中間件可以一起工作,每個中間件可以獨立執行其操作。以下是一個使用 LoggerMiddleware
和 CustomPropertyMiddleware
的示例:
1import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";2import { LoggerMiddleware } from "./logger.middleware";3import { CustomPropertyMiddleware } from "./custom-property.middleware";4
5@Module({6 // 其他模塊配置7})8export class AppModule implements NestModule {9 configure(consumer: MiddlewareConsumer) {10 consumer.apply(LoggerMiddleware, CustomPropertyMiddleware).forRoutes("*");11 }12}
在上面的示例中,LoggerMiddleware
會記錄請求日誌,CustomPropertyMiddleware
會在請求對象中添加自定義屬性。所有請求都會經過這兩個中間件。
forRoutes 和 exclude 的多種用法
forRoutes
方法可以指定中間件應用於特定的路徑、控制器或方法。
應用於特定路徑
1consumer2 .apply(LoggerMiddleware)3 .forRoutes({ path: "cats", method: RequestMethod.GET });
應用於特定控制器
1import { CatsController } from "./cats.controller";2
3consumer.apply(LoggerMiddleware).forRoutes(CatsController);
應用於多個路徑和方法
1consumer2 .apply(LoggerMiddleware)3 .forRoutes(4 { path: "cats", method: RequestMethod.GET },5 { path: "dogs", method: RequestMethod.POST },6 );
排除特定路徑
exclude
方法用於排除特定路徑,使中間件不應用於這些路徑:
1consumer2 .apply(LoggerMiddleware)3 .exclude(4 { path: "cats", method: RequestMethod.GET },5 { path: "dogs", method: RequestMethod.POST },6 )7 .forRoutes("*");
在上面的示例中,LoggerMiddleware
會應用於所有路徑,除了 GET /cats
和 POST /dogs
。
Functional 中間件
除了類中間件,NestJS 還支持使用函數創建中間件。以下是一個函數中間件示例:
1import { Request, Response, NextFunction } from "express";2
3export function logger(req: Request, res: Response, next: NextFunction) {4 console.log(`Request...`);5 next();6}
使用函數中間件時,不需要實現 NestMiddleware
介面。可以直接在模塊中應用:
1import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";2import { logger } from "./logger.middleware";3
4@Module({5 // 其他模塊配置6})7export class AppModule implements NestModule {8 configure(consumer: MiddlewareConsumer) {9 consumer.apply(logger).forRoutes("*");10 }11}
總結
本文詳細介紹了 NestJS 中間件的概念,並講解了如何創建和應用中間件來處理請求和響應。通過使用中間件,開發者可以在請求處理過程中執行各種操作,如身份驗證、日誌記錄和請求修改,從而增強應用程序的功能和安全性。我們還展示了多個中間件協作的示例,說明了如何修改請求和響應對象,以及如何使用 forRoutes
和 exclude
方法來控制中間件的應用範圍。此外,還介紹了如何創建和應用函數中間件。