在 NestJS 中,可以通过创建一个中间件来为所有的请求统一添加一个参数或属性。中间件是一个可以在处理请求之前对请求进行操作的函数。你可以利用中间件来添加、修改或验证请求中的内容。
下面是如何实现一个全局中间件,使所有请求都带上一个参数(比如 userId)的示例:
1. 创建中间件
首先,你需要创建一个中间件。在 NestJS 中,中间件可以是类、函数或基于函数的类。这里我们以类为例。
nest generate middleware add-user-id
这将生成一个基础的中间件类,你可以在其中实现具体逻辑。
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class AddUserIdMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
// 假设你想在每个请求中添加一个 userId
req.headers['user-id'] = '12345'; // 这里添加 userId 到请求头
// 你也可以将参数添加到请求对象的其他部分
// req.body.userId = '12345'; // 添加到请求体
// req.query.userId = '12345'; // 添加到 URL 参数
next(); // 继续处理下一个中间件或控制器
}
}
2. 应用中间件
中间件创建好后,你需要在你的应用程序中将它应用到所有路由上。
有两种方式可以应用中间件:全局应用和模块级应用。
全局应用:
你可以在 main.ts 中通过 app.use() 方法全局应用中间件:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AddUserIdMiddleware } from './add-user-id.middleware';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(AddUserIdMiddleware); // 全局应用中间件
await app.listen(3000);
}
bootstrap();
模块级应用:
如果你只想在某个模块中应用中间件,可以在该模块的 configure 方法中使用 MiddlewareConsumer:
import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AddUserIdMiddleware } from './add-user-id.middleware';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(AddUserIdMiddleware)
.forRoutes('*'); // 对所有路由生效,或者可以指定特定路由
}
}
如果你想让中间件只对特定的 HTTP 方法或路由生效,可以这样配置:
consumer
.apply(AddUserIdMiddleware)
.forRoutes({ path: 'some-route', method: RequestMethod.GET });
3. 访问添加的参数
中间件已经将 userId 添加到请求对象中,现在你可以在控制器或服务中访问这个参数。
import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';
@Controller('example')
export class ExampleController {
@Get()
getExample(@Req() req: Request) {
const userId = req.headers['user-id']; // 获取请求头中的 userId
return `User ID is ${userId}`;
}
}
通过这种方式,你可以确保所有请求都携带特定的参数,比如 userId,而无需在每个控制器或服务中手动添加这个逻辑。这种方法对于应用统一的请求前处理非常有用。