深入理解NestJS中间件:创建和应用中间件处理请求与响应

在 NestJS 中,中间件(Middleware)是处理请求和响应的重要组件。本文将详细介绍 NestJS 中间件的概念,并讲解如何创建和应用中间件来处理请求和响应。

什么是中间件

在 NestJS 中,中间件是一个函数,它可以访问请求对象(req)、响应对象(res)和应用程序请求-响应周期中的下一个中间件函数(next)。中间件可以在处理请求前进行操作,例如验证用户身份、记录日志、修改请求对象等。

中间件的定义与使用方式类似于 Express.js,但 NestJS 提供了更强大的模块化和类型安全支持。

创建中间件

要创建一个中间件,需要实现 NestMiddleware 接口并定义 use 方法。以下是一个简单的日志记录中间件示例:

1
import { Injectable, NestMiddleware } from "@nestjs/common";
2
import { Request, Response, NextFunction } from "express";
3
4
@Injectable()
5
export 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 应用于所有路由的示例:

1
import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";
2
import { LoggerMiddleware } from "./logger.middleware";
3
4
@Module({
5
// 其他模块配置
6
})
7
export class AppModule implements NestModule {
8
configure(consumer: MiddlewareConsumer) {
9
consumer.apply(LoggerMiddleware).forRoutes("*");
10
}
11
}

apply 方法指定要应用的中间件,forRoutes 方法指定中间件的应用范围。forRoutes('*') 表示将中间件应用于所有路由。

中间件示例

修改请求对象

下面的中间件会添加一个自定义属性 customProperty 到请求对象中:

1
import { Injectable, NestMiddleware } from "@nestjs/common";
2
import { Request, Response, NextFunction } from "express";
3
4
@Injectable()
5
export class CustomPropertyMiddleware implements NestMiddleware {
6
use(req: Request, res: Response, next: NextFunction) {
7
req["customProperty"] = "Custom Value";
8
next();
9
}
10
}

修改响应对象

以下是一个修改响应对象的中间件示例:

1
import { Injectable, NestMiddleware } from "@nestjs/common";
2
import { Request, Response, NextFunction } from "express";
3
4
@Injectable()
5
export 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
}

多个中间件协作

多个中间件可以一起工作,每个中间件可以独立执行其操作。以下是一个使用 LoggerMiddlewareCustomPropertyMiddleware 的示例:

1
import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";
2
import { LoggerMiddleware } from "./logger.middleware";
3
import { CustomPropertyMiddleware } from "./custom-property.middleware";
4
5
@Module({
6
// 其他模块配置
7
})
8
export class AppModule implements NestModule {
9
configure(consumer: MiddlewareConsumer) {
10
consumer.apply(LoggerMiddleware, CustomPropertyMiddleware).forRoutes("*");
11
}
12
}

在上面的示例中,LoggerMiddleware 会记录请求日志,CustomPropertyMiddleware 会在请求对象中添加自定义属性。所有请求都会经过这两个中间件。

forRoutes 和 exclude 的多种用法

forRoutes 方法可以指定中间件应用于特定的路径、控制器或方法。

应用于特定路径

1
consumer
2
.apply(LoggerMiddleware)
3
.forRoutes({ path: "cats", method: RequestMethod.GET });

应用于特定控制器

1
import { CatsController } from "./cats.controller";
2
3
consumer.apply(LoggerMiddleware).forRoutes(CatsController);

应用于多个路径和方法

1
consumer
2
.apply(LoggerMiddleware)
3
.forRoutes(
4
{ path: "cats", method: RequestMethod.GET },
5
{ path: "dogs", method: RequestMethod.POST },
6
);

排除特定路径

exclude 方法用于排除特定路径,使中间件不应用于这些路径:

1
consumer
2
.apply(LoggerMiddleware)
3
.exclude(
4
{ path: "cats", method: RequestMethod.GET },
5
{ path: "dogs", method: RequestMethod.POST },
6
)
7
.forRoutes("*");

在上面的示例中,LoggerMiddleware 会应用于所有路径,除了 GET /catsPOST /dogs

Functional 中间件

除了类中间件,NestJS 还支持使用函数创建中间件。以下是一个函数中间件示例:

1
import { Request, Response, NextFunction } from "express";
2
3
export function logger(req: Request, res: Response, next: NextFunction) {
4
console.log(`Request...`);
5
next();
6
}

使用函数中间件时,不需要实现 NestMiddleware 接口。可以直接在模块中应用:

1
import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";
2
import { logger } from "./logger.middleware";
3
4
@Module({
5
// 其他模块配置
6
})
7
export class AppModule implements NestModule {
8
configure(consumer: MiddlewareConsumer) {
9
consumer.apply(logger).forRoutes("*");
10
}
11
}

总结

本文详细介绍了 NestJS 中间件的概念,并讲解了如何创建和应用中间件来处理请求和响应。通过使用中间件,开发者可以在请求处理过程中执行各种操作,如身份验证、日志记录和请求修改,从而增强应用程序的功能和安全性。我们还展示了多个中间件协作的示例,说明了如何修改请求和响应对象,以及如何使用 forRoutesexclude 方法来控制中间件的应用范围。此外,还介绍了如何创建和应用函数中间件。

美团外卖红包 饿了么红包 支付宝红包