Nestjs中间件给所有请求统一加上一个请求参数

329 阅读2分钟

在 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,而无需在每个控制器或服务中手动添加这个逻辑。这种方法对于应用统一的请求前处理非常有用。