NestJS 异常过滤器不应该捕获事件发射器错误吗?
我正在重构的 NestJS 应用程序上运行一些手动测试,并且刚刚从 Nest 的全局异常过滤器中发现了奇怪的行为。 创建该项目的开发人员将其用作异常过滤器:
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
} from '@nestjs/common';
import { HttpAdapterHost } from '@nestjs/core';
import { LoggerService } from '../../config/logger.service';
@Catch()
export class GlobalExceptionsFilter implements ExceptionFilter {
constructor(
private readonly httpAdapterHost: HttpAdapterHost,
private readonly logger: LoggerService,
) {}
catch(exception: Error, host: ArgumentsHost): void {
const { httpAdapter } = this.httpAdapterHost;
const ctx = host.switchToHttp();
const httpStatus =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const responseBody = {
statusCode: httpStatus,
path: httpAdapter.getRequestUrl(ctx.getRequest()),
cause: `${exception.name}: ${exception.message}`,
timestamp: new Date().toISOString(),
};
this.logger.error(responseBody?.cause);
httpAdapter.reply(ctx.getResponse(), responseBody, httpStatus);
}
}
这与 中的 catch-everything 过滤器示例几乎完全相同Nest 的文档,所以它确实非常通用。
在该项目的某个部分中,有一个控制器具有如下内容:
@OnEvent(Events.POTATO_EVENT)
async potatoMethod(payload) {
return await this.service.potatoMethod(payload);
当前,服务的 potatoMethod
上没有有效负载验证,因此控制器使用 EventEmitter2
从另一个服务接收有效负载code> 并将其转发到其服务,然后该服务尝试通过调用 ORM 方法来获取数据库中的记录。 如果 payload.potatoNumber
发送正确,不会发生任何错误,但是如果我将 payload.potatoNumber
发送为未定义,ORM 将抛出一个错误,该错误不会被该全局捕获筛选。 如果我不使用 @OnEvent()
而直接在控制器上使用 @Get()
将其转换为端点,则不会发生同样的事情。
目前,main
看起来像这样:
(async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
})();
我可能完全错了,但只有当应用程序未在其 main 上使用
文件,对吗?如果是肯定的,微服务在 Nest 中到底是如何工作的?NestFactory.createMicroservice()
时,才会发生这种情况.ts
I'm running some manual tests on a NestJS application I'm refactoring and just found an odd behaviour from nest's global exception filter.
The developer who created this project used this as a exception filter:
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
} from '@nestjs/common';
import { HttpAdapterHost } from '@nestjs/core';
import { LoggerService } from '../../config/logger.service';
@Catch()
export class GlobalExceptionsFilter implements ExceptionFilter {
constructor(
private readonly httpAdapterHost: HttpAdapterHost,
private readonly logger: LoggerService,
) {}
catch(exception: Error, host: ArgumentsHost): void {
const { httpAdapter } = this.httpAdapterHost;
const ctx = host.switchToHttp();
const httpStatus =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const responseBody = {
statusCode: httpStatus,
path: httpAdapter.getRequestUrl(ctx.getRequest()),
cause: `${exception.name}: ${exception.message}`,
timestamp: new Date().toISOString(),
};
this.logger.error(responseBody?.cause);
httpAdapter.reply(ctx.getResponse(), responseBody, httpStatus);
}
}
Which is almost exactly the same catch-everything filter example in Nest's docs, so it's very generic, indeed.
In a certain part of this project, there's a controller with something like this:
@OnEvent(Events.POTATO_EVENT)
async potatoMethod(payload) {
return await this.service.potatoMethod(payload);
Currently, there's no payload validation on the service's potatoMethod
, so the controller receives a payload from another service using EventEmitter2
and forwards it to it's service, which then tries to fetch a record on the database by calling an ORM method.
If payload.potatoNumber
is sent correctly, nothing wrong happens, but if I send payload.potatoNumber
as undefined, the ORM will throw an error that will not be caught on that global filter.
The same thing doesn't happen if instead of using a @OnEvent()
I just use a @Get()
directly on the controller to turn it into an endpoint.
Currently, main
looks something like this:
(async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
})();
I might be completely wrong, but this should only happen if the application is not using NestFactory.createMicroservice()
on it's main.ts
file, right? If positive, how exactly does microservices work natively in Nest?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我对 nestjs 事件发射器 1.4.1 中的这种行为也感到有点措手不及,但同时它的发生也是有道理的,除非您自己处理这些异常。
但他们最终在 https://github.com/nestjs/ 中添加了这种类型的处理event-emitter/pull/908,因此您只需更新到事件发射器 2.0.1 或更高版本(在本答案时为 2.0.4)。
I was also caught a bit off guard with this behaviour in nestjs event emitter 1.4.1, but at the same time it makes sense it happens unless you handle those exceptions yourself.
But they ended up adding that type of handling in https://github.com/nestjs/event-emitter/pull/908, so you just need to update to event emitter 2.0.1 or greater (2.0.4 at the time of this answer).