NestJS中继承BaseExceptionFilter的过滤器注入HttpServer问题
NestJS中继承BaseExceptionFilter时HttpServer注入失败的解决方案
当实现继承BaseExceptionFilter的全局异常过滤器并注入自定义日志服务时,通过APP_FILTER令牌注册时会遇到HttpServer参数无法正确注入的问题,以下是可行的解决方法:
方法一:通过HttpAdapterHost间接获取适配器
调整过滤器的构造函数,注入HttpAdapterHost并从中提取httpAdapter传入父类构造函数,这是Nest官方推荐的获取当前HTTP适配器的方式:
import { Injectable, Catch, HttpException, ArgumentsHost, HttpAdapterHost } from '@nestjs/common'; import { BaseExceptionFilter } from '@nestjs/core'; import { StructuredLogger } from './path-to-your-logger'; @Catch() @Injectable() export class UncaughtExceptionFilter extends BaseExceptionFilter { constructor( private readonly logger: StructuredLogger, private readonly httpAdapterHost: HttpAdapterHost, ) { // 将HttpAdapter传入父类构造函数,它实现了HttpServer接口 super(httpAdapterHost.httpAdapter); } catch(exception: any, host: ArgumentsHost) { if (exception instanceof HttpException) { super.catch(exception, host); } else { this.logger.error(exception, 'uncaught'); const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const status = 500; response.status(status).json({ statusCode: status, message: 'Internal server error', }); } } }
在模块中正常注册全局过滤器即可:
import { Module, APP_FILTER } from '@nestjs/common'; import { UncaughtExceptionFilter } from './path-to-your-filter'; import { StructuredLogger } from './path-to-your-logger'; @Module({ providers: [ StructuredLogger, { provide: APP_FILTER, useClass: UncaughtExceptionFilter, }, ], }) export class AppModule {}
方法二:使用工厂提供者手动构造实例
如果上述方法仍有问题,可以通过工厂函数手动创建过滤器实例,明确注入所需依赖:
import { Module, APP_FILTER } from '@nestjs/common'; import { UncaughtExceptionFilter } from './path-to-your-filter'; import { StructuredLogger } from './path-to-your-logger'; import { HttpAdapterHost } from '@nestjs/core'; @Module({ providers: [ StructuredLogger, { provide: APP_FILTER, useFactory: (logger: StructuredLogger, httpAdapterHost: HttpAdapterHost) => { return new UncaughtExceptionFilter(logger, httpAdapterHost.httpAdapter); }, // 声明需要注入的依赖 inject: [StructuredLogger, HttpAdapterHost], }, ], }) export class AppModule {}
此时过滤器的构造函数可以保持原有定义:
constructor( private readonly logger: StructuredLogger, applicationRef: HttpServer, ) { super(applicationRef); }
关键说明
直接注入HttpServer或使用HTTP_SERVER_REF令牌失败,是因为全局过滤器的注册上下文与普通服务的依赖注入上下文存在差异,而HttpAdapterHost是Nest专门设计用于在任意上下文下获取当前HTTP适配器的服务,能确保拿到正确的实例供BaseExceptionFilter使用。
内容的提问来源于stack exchange,提问作者user3896248
相关产品推荐
相关产品推荐

