Nestjs:从装饰器中检索请求/上下文

Nestjs: Retrieve the request / context from a Decorator

我正在做一个 NestJS 项目, 我正在尝试让 executionContext 在记录器中可访问以按请求过滤日志。

我对每个可注入对象都有一个记录器实例,我想保持这种行为(因此可注入对象的范围是默认的)。

为此,我试图创建一个装饰器,从请求中获取上下文并将其传递给子服务(如在记录器中),最终在记录器中获取上下文...

我不确定是否清楚...现在,这是我的代码:

export const Loggable = () => (constructor: Function) => {
  for (const propertyName of Reflect.ownKeys(constructor.prototype)) {
    let descriptor = Reflect.getOwnPropertyDescriptor(constructor.prototype, propertyName);
    const isMethod = descriptor.value instanceof Function;
    if (!isMethod)
      continue;

    const originalMethod = descriptor.value;
    const routeArgsMetada = Reflect.getMetadata(ROUTE_ARGS_METADATA, constructor, propertyName as string);

    descriptor.value = function (...args: any[]) {
      const result = originalMethod.apply(this, args);
        //TODO : retrieve the request / contextExecution
        //TODO : pass the request / contextExecution to children functions...
      return result;
    };
    Reflect.defineProperty(constructor.prototype, propertyName, descriptor);

    Reflect.defineMetadata(ROUTE_ARGS_METADATA, routeArgsMetada, constructor, propertyName as string);
  }
};

这个@Loggable()装饰器将附加到所有需要记录或抛出执行上下文的可注入类

这可能吗?如果不是,为什么?

PS:我想知道,@Guard 注解是如何获取上下文的?以及@Req 注解如何获取请求?

https://github.com/nestjs/nest/tree/master/packages/common/decorators/http

https://github.com/nestjs/nest/blob/master/packages/common/decorators/core/use-guards.decorator.ts

@Req 是如何获取请求的?

从这里下载 NestJS 的源代码:https://github.com/nestjs/nest

并在 TS 文件中查找 'RouteParamtypes.REQUEST'。您可以在这里找到它们:

  • 路线-params.decorator.ts
  • 路由参数-factory.ts

如您所见,装饰器通常不会做太多。他们只是将一些元数据添加到 类、方法和参数。剩下的都做框架。

这里@Req只是在启动时创建一个特殊的参数装饰器,在调用方法之前由RouteParamsFactory处理。

export const Request: () => ParameterDecorator = createRouteParamDecorator(
  RouteParamtypes.REQUEST,
);

所以请求不是由@Req 装饰器本身检索的。它只要求NestJS框架在调用方法之前用Request的引用填充注解的方法参数。

顺便说一句,我也遇到了和你一样的问题。我也在寻找关于如何从装饰器访问 ExecutionContext 的解决方案。但是装饰器只能访问带注释的目标(类、处理程序、参数...)

我认为 ExecutionContext 只能从以下位置直接访问:

  • 管道
  • 守卫
  • 拦截器

或通过这种方式从参数装饰器: https://docs.nestjs.com/custom-decorators#param-decorators

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const User = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    return request.user;
  },
);

注意:您可以在 create-route-param-metadata.decorator.ts 中找到 createParamDecorator() 的源代码。