简体   繁体   English

Nestjs拦截器没有被调用

[英]Nestjs Interceptor not being invoked

I am using NestJS with a serverless app (deployed to AWS Lambda).我将 NestJS 与无服务器应用程序(部署到 AWS Lambda)一起使用。 I now have a need to use middleware, or Interceptors as they are called in nest, but I'm struggling to get them to work.我现在需要使用中间件或拦截器,因为它们在嵌套中被调用,但我正在努力让它们工作。 I have changed from using NestFactory.createApplicationContext to NestFactory.create , as per the docs, that's what wraps Controller methods with enhancers, eg Interceptors根据文档,我已从使用NestFactory.createApplicationContext更改为NestFactory.create ,这就是使用增强器(例如拦截器)包装 Controller 方法的原因

I am registering the Interceptor in a module, so it should be globally available我在一个模块中注册拦截器,所以它应该是全局可用的

const loggingInterceptorProvider = {
  provide: APP_INTERCEPTOR,
  useClass: LoggingInterceptor,
};

My bootstrap looks like so我的引导程序看起来像这样

export async function bootstrap(Module: any) {
  if (app) return app;
  app = await NestFactory.createApplicationContext(Module);
 return await app.init();
}

Now the non-standard bit, because I am using a generic "builder" (library code), the builder is passed the controller name as a string, and it is then invoked, as such现在是非标准位,因为我使用的是通用“构建器”(库代码),构建器将 controller 名称作为字符串传递,然后调用它,因此

// the Module is accessible in the bootstrap via a closure, not shown in this code
const app = await bootstrap();
const appController = app.get(Controller);
// functionName is a string
const controllerFunction = appController[functionName];

const boundControllerFunction = controllerFunction.bind(
  appController,
);

const result = await boundControllerFunction(body);

I am not seeing any of my Interceptor logging output.我没有看到我的任何拦截器记录 output。 Am I doing something wrong?难道我做错了什么? Or is it the way I am invoking the Controller that is not working with Interceptors?还是我调用不与拦截器一起使用的 Controller 的方式?

EDIT:编辑:

For completeness, this is the correct bootstrap function I use为了完整起见,这是我使用的正确引导程序 function

let cachedApp: INestApplication;
export async function bootstrap(Module: any) {
  if (cachedApp) return cachedApp;

  cachedApp = await NestFactory.create(Module, {
    bufferLogs: true,
    logger: ['error', 'warn'],
  });

  await cachedApp.init();

  return cachedApp;
}

It happens because you've called the controller method directly, bypassing the nestjs lifecycle.这是因为您直接调用了 controller 方法,绕过了 nestjs 生命周期。 When nest js server handles the request it applies its internal mechanisms for running interceptors, validation pipes, and exception filters.当 Nest js 服务器处理请求时,它会应用其内部机制来运行拦截器、验证管道和异常过滤器。 If you call class method directly it will not be used.如果直接调用 class 方法将不会被使用。

In your case you can follow this section of nestjs documentation:在您的情况下,您可以遵循nestjs文档的这一部分:

https://docs.nestjs.com/faq/serverless#example-integration https://docs.nestjs.com/faq/serverless#example-integration

let server: Handler;

async function bootstrap(): Promise<Handler> {
  const app = await NestFactory.create(AppModule);
  await app.init();

  const expressApp = app.getHttpAdapter().getInstance();
  return serverlessExpress({ app: expressApp });
}

export const handler: Handler = async (
  event: any,
  context: Context,
  callback: Callback,
) => {
  server = server ?? (await bootstrap());
  return server(event, context, callback);
};

The "standalone application feature" from docs is useful if you want to call some service code, not a controller.如果您想调用一些服务代码,而不是 controller,则文档中的“独立应用程序功能”非常有用。


By the way, in the code snippet, you can see the variable server , they moved it outside of a handler function intentionally.顺便说一句,在代码片段中,您可以看到变量server ,他们故意将其移到处理程序 function 之外。 Because in AWS lambdas it can be cached between different requests.因为在 AWS lambdas 中,它可以在不同的请求之间缓存。

I found a/the way to do it, using the very poorly documented feature ExternalContextCreator .我找到了一种方法来做到这一点,使用记录很差的功能ExternalContextCreator So basically the last code snippet I posted above, would become this所以基本上我上面发布的最后一个代码片段会变成这个

  import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator';   

  // the Module is accessible in the bootstrap via a closure, not shown in this code
  const app = await bootstrap();
  const appController = app.get(Controller);
  // functionName is a string
  const controllerFunction = appController[functionName];

  const extContextCreator = app.get(ExternalContextCreator);

  const boundControllerFunction = extContextCreator.create(
    appController,
    controllerFunction,
    String(functionName),
  );

  const result = await boundControllerFunction(body);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM