NestJS使用useFactory从Request注入USER至DI报错求助
解决NestJS中通过DI注入请求级用户实例的问题
核心问题分析
你遇到的req为undefined的原因是:默认的DI Provider是单例作用域,在应用启动时就初始化完成,此时还没有请求上下文,自然拿不到当前请求对象;而@Req()装饰器仅能在控制器方法、守卫、拦截器等请求上下文的场景中使用,无法直接用于Provider的工厂函数。
正确实现方案
要注入请求级的req.user,需要创建请求作用域的Provider,并通过NestJS内置的REQUEST令牌注入当前请求对象。
1. 创建请求作用域的USER Provider
在模块中定义USER Provider时,指定作用域为Scope.REQUEST,并注入REQUEST对象来获取当前请求:
import { Module, Scope, Inject } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { Request } from 'express'; // 若使用Fastify则导入fastify的Request类型 @Module({ providers: [ { provide: 'USER', useFactory: (req: Request) => { // 这里可以直接获取中间件挂载的req.user return req.user; }, inject: [REQUEST], // 注入当前请求对象 scope: Scope.REQUEST, // 标记为请求作用域,每个请求生成新实例 }, ], exports: ['USER'], // 若其他模块需要使用,需导出该Provider }) export class UserModule {}
2. 控制器中注入USER实例
在控制器中直接通过@Inject('USER')注入即可,NestJS会自动为每个请求绑定对应的用户实例:
import { Controller, Get, Inject } from '@nestjs/common'; import { User } from './user.entity'; // 替换为你的用户实体类型 @Controller('profile') export class ProfileController { constructor(@Inject('USER') private readonly currentUser: User) {} @Get() getCurrentUserProfile() { return this.currentUser; } }
3. 确保中间件执行顺序
要保证中间件在控制器之前执行,确保req.user已被正确挂载。在根模块中注册中间件:
import { MiddlewareConsumer, Module } from '@nestjs/common'; import { AuthMiddleware } from './auth.middleware'; import { ProfileController } from './profile.controller'; import { UserModule } from './user.module'; @Module({ imports: [UserModule], controllers: [ProfileController], }) export class AppModule { configure(consumer: MiddlewareConsumer) { consumer .apply(AuthMiddleware) .forRoutes('profile'); // 或使用`.forRoutes('*')`全局注册 } }
注意事项
- 请求作用域的Provider会为每个请求创建新实例,对于高并发场景会有轻微性能开销,但NestJS对该场景做了优化,普通业务场景可忽略。
- 若使用Fastify框架,需将
Request类型替换为import { Request } from 'fastify';。
内容的提问来源于stack exchange,提问作者Zoltan Hernyak
相关产品推荐
相关产品推荐

