NestJS使用Reflector无法获取自定义Public装饰器值,抛出TypeError
无法获取Public装饰器值,抛出TypeError问题解决
我无法获取自定义的用于公开路由的Public装饰器的值,总是抛出ERROR [ExceptionsHandler] TypeError错误。以下是我的auth.middleware.ts代码:
// auth.middleware.ts import { Injectable, NestMiddleware, Reflector } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; @Injectable() export class AuthMiddleware implements NestMiddleware { constructor(private readonly reflector: Reflector) {} use(req: Request, res: Response, next: NextFunction) { const isPublic = this.reflector.get<boolean>('isPublic', req.route?.stack[0]?.method); console.log('isPublic:', isPublic); if (!isPublic) { // Implement your authentication logic here // For example, you can use JWT verification // and attach the user to the request: req.user = decodedUser; } next(); } }
问题原因
代码中req.route?.stack[0]?.method返回的是HTTP方法字符串(如GET、POST),而Nest的元数据是附加在控制器类或路由方法对象上的,并非字符串类型。用字符串作为reflector.get的目标参数,会直接触发类型错误。
解决步骤
1. 确认Public装饰器定义正确
确保你的Public装饰器是通过SetMetadata正确定义的:
// public.decorator.ts import { SetMetadata } from '@nestjs/common'; export const Public = () => SetMetadata('isPublic', true);
2. 修改中间件获取元数据的逻辑
将获取isPublic的代码改为从路由对应的控制器类和方法对象上读取元数据:
// auth.middleware.ts(修改后) import { Injectable, NestMiddleware, Reflector } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; @Injectable() export class AuthMiddleware implements NestMiddleware { constructor(private readonly reflector: Reflector) {} use(req: Request, res: Response, next: NextFunction) { // 获取路由对应的处理函数 const handler = req.route?.stack[0]?.handle; // 从控制器类和处理方法上合并获取isPublic元数据 const isPublic = this.reflector.getAllAndOverride<boolean>('isPublic', [ handler?.constructor, handler, ]); console.log('isPublic:', isPublic); if (!isPublic) { // 实现你的认证逻辑,比如JWT验证并将用户信息挂载到req上 // req.user = decodedUser; } next(); } }
3. 确认装饰器正确应用
确保在需要公开的路由方法上正确使用@Public()装饰器:
// example.controller.ts import { Controller, Get } from '@nestjs/common'; import { Public } from './public.decorator'; @Controller('example') export class ExampleController { @Public() @Get('public') getPublicData() { return { message: '这是公开数据' }; } @Get('private') getPrivateData() { return { message: '这是需要认证的私有数据' }; } }
内容的提问来源于stack exchange,提问作者Chinjen Adrian
相关产品推荐
相关产品推荐

