nestjs - 拦截器没有捕捉到由 Nestjs 中的守卫引发的错误
问题描述
我有一个在应用程序中注册的全局警卫,common.module.ts
它是一个全局模块。
const HeaderGuardGlobal = {
provide: APP_GUARD,
useClass: HeaderGuard
};
@Global()
@Module({
imports: [ LoggerModule ],
providers: [ HeaderGuardGlobal ],
exports: []
})
header.guard.ts:
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const userName = request.headers[HEADERS.USER_NAME];
if(!userName) {
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}
我有一个控制范围的拦截器authenticate-header.interceptor.ts
@Injectable()
export class setAuthenticateHeaderInterceptor<T> implements NestInterceptor<T, Response<T>> {
public constructor() {}
intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
const req = context.switchToHttp().getRequest();
const res = context.switchToHttp().getResponse();
return next
.handle()
.pipe(
catchError(err => {
console.log('ERROR: ', err);
res.setHeader('sampleKey', 'sampleValue');
return throwError(err);
})
)
}
}
user.controller.ts:
@Controller('user')
@UseInterceptors(setAuthenticateHeaderInterceptor)
export class ClientController {
我想要实现的是,当header.guard.ts
抛出Forbidden
异常时,authenticate-header.interceptor.ts
会捕获异常并将其传播到全局 http-filter,但在此之前我想向响应对象添加一个标头。
我面临的问题是当警卫抛出异常时,拦截器无法捕获它。但是,当路由处理程序或服务抛出相同的错误时,拦截器能够捕获它。
我通过请求生命周期来了解执行上下文,并在拦截器部分找到了以下语句。
管道、控制器或服务抛出的任何错误都可以在拦截器的 catchError 运算符中读取。
该声明没有提到任何关于警卫的内容,所以我假设我想要实现的目标是不可能的。
我无法弄清楚为什么拦截器没有捕获到守卫内引发的错误。如果有人觉得需要更多信息,上面的代码片段仅包含我认为对问题必要的部分。然后我会提供它。
解决方案
正如您所提到的,文档正确地说明了,
管道、控制器或服务抛出的任何错误都可以在拦截器的 catchError 运算符中读取。
正如下面总结部分中提到的,守卫在拦截器之前执行,因此,它们的错误无法在拦截器的catchError
方法中被捕获。你最好的选择是制作一个扩展你的过滤器,GlobalFilter
在那里添加你的逻辑,然后调用super.catch(exception)
调用其余的逻辑。
推荐阅读
- flutter - 在 Flutter 中对齐多行 TextField 中的提示文本
- mysql - MySQL 更新表 w/o 将额外值设置为 null
- shopware - 未知列
_id on Shopware 6 翻译 - r - 生成日期序列时出错-“来自”必须是有限数
- r - Plotly:如何为地图设置 ylim 和 xlim?
- django - 将子对象与Django中每个实例的父对象相关联?
- javascript - 通过脚本标签导入与通过 webpack 导入
- selenium - 量角器中的“goog:chromeOptions”与 chromeOptions
- ffmpeg - FFMPEG 复制第一帧
- python - 继续遇到这个问题,在数据框中插入一个爆炸