Nest HttpExceptionFilter异常过滤器 拦截器 中间件
异常过滤器
@UseFilters
@UseFilters 用于设置异常过滤器,作用于控制器 MethodDecorator & ClassDecorator:
import { Controller, UseFilters } from '@nestjs/common';
@Controller('user')
@UseFilters(MyHttpExceptionFilter, OtherFilter)
export class UserController {
@Get()
@UseFilters(MyHttpExceptionFilter, OtherFilter)
async fn() {}
...
}
如果需要全局过滤器:
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { ConfigService } from '@nestjs/config';
import { AppModule } from './app.module';
import { text } from 'body-parser';
import * as xmlparser from 'express-xml-bodyparser';
import * as cookieParser from 'cookie-parser';
import { join } from 'path';
import { GlobalExceptionFilter } from './common/filter/global.filter';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.enableCors();
app.use(cookieParser());
app.use(text());
app.use(xmlparser());
app.useStaticAssets(join(process.cwd(), 'public'));
app.useGlobalFilters(new GlobalExceptionFilter()); // 设置全局异常过滤器
const configService = app.get(ConfigService);
process.title = configService.get<string>('TITLE');
const PORT = configService.get<number>('PORT');
await app.listen(PORT);
console.log(`server running at port:${PORT}`);
}
bootstrap();
这种情况下,过滤器不能使用依赖注入,怎么办呢?只能手动获取了:
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
const configService = app.get(ConfigService);
app.useGlobalFilters(new GlobalExceptionFilter(configService));
process.title = configService.get<string>('TITLE');
}
BaseExceptionFilter
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus } from '@nestjs/common';
import { BaseExceptionFilter } from '@nestjs/core';
import { Request, Response } from 'express';
@Catch(Error)
export class GlobalExceptionFilter extends BaseExceptionFilter implements ExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
if (exception instanceof HttpException) {
return this.catchHttpException(exception, host);
}
if (exception instanceof Error) {
return this.catchError(exception, host);
}
// return super.catch(exception, host) // 使用 @Catch() 捕获全部抛出可能运行到此,但是如果不注入 HttpAdapterHost 依赖则 BaseExceptionFilter 会抛异常
}
catchError(exception: Error, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
response
.status(HttpStatus.BAD_GATEWAY)
.json({
error: 'ERROR!'
})
}
catchHttpException(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
response
.status(status)
.json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
全局过滤器可以继承基本过滤器,需要手动注入 HttpAdapterHost 依赖:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const { httpAdapter } = app.get(HttpAdapterHost);
app.useGlobalFilters(new AllExceptionsFilter(httpAdapter));
await app.listen(3000);
}
bootstrap();
注意
异常过滤器只能捕获控制器内抛出的异常,不能捕获拦截器和中间件抛出的异常,这些异常会导致整个应用程序停止运行,因此要小心使用。
通常,对于 Observable 进行 pipe 或者 subscribe 操作时,需要处理好 catchError操作 和 error(e) 回调。
拦截器
@UseInterceptors
@UseInterceptors 用于设置拦截器,作用于控制器 MethodDecorator & ClassDecorator:
import { Controller, UseInterceptors } from '@nestjs/common';
@Controller('user')
@UseFilters(A, B)
export class UserController {
@Get()
@UseInterceptors(C)
async fn() {}
...
}
也可以设置全局拦截器:
app.useGlobalInterceptors(A, B, C);