拦截器未捕获NestJS中警卫抛出的错误

时间:2020-04-07 19:19:01

标签: 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过滤器,但是在执行之前我想在响应对象中添加标题。

我面临的问题是当守卫抛出异常时,拦截器无法捕获它。但是,当从路由处理程序或服务中抛出相同的错误时,拦截器便可以捕获该错误。

我通过request-lifecycle来了解执行上下文,并在interceptors部分找到了以下语句。

管道,控制器或服务抛出的任何错误都可以在拦截器的catchError运算符中读取。

该声明未提及任何有关警卫的信息,因此我假设我试图实现的目标是不可能的。

我无法弄清楚为什么拦截器没有捕获到在警卫内部抛出的错误。如果有人觉得需要更多信息,以上代码片段仅包含我认为对该问题必要的部分。然后我将提供它。

1 个答案:

答案 0 :(得分:0)

您所提到的文档正确陈述了

管道,控制器或服务抛出的任何错误都可以在拦截器的catchError运算符中读取。

如以下summary部分所述,

防护程序在拦截器执行之前执行,因此,它们的错误无法在拦截器的# test_b.py import non_test import configs import importlib importlib.reload(non_test) importlib.reload(configs) def test_class(): SomeClass() 方法中捕获。最好的选择是制作一个扩展catchError的过滤器,在其中添加逻辑,然后调用GlobalFilter来调用其余的逻辑。