NestJS - Exception Filter总结

712 阅读2分钟

Nest 带有一个内置的异常层,负责处理应用程序中所有未经处理的异常。当应用程序代码未处理异常时,该异常将被该层捕获,然后该层自动发送适当的用户友好响应

截屏2023-11-05 22.16.23.png 该筛选器处理类型 HttpException (及其子类)的异常。

如:

throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);

得到的响应:

{
	"statusCode": 403,
	"message": "Forbidden"
}

当异常无法识别(既不是 HttpException 也不是继承自 HttpException 的类)时,内置异常筛选器将生成以下默认 JSON 响应:

{
  "statusCode": 500,
  "message": "Internal server error"
}

HttpException 标准异常

Nest 提供了一个内置 HttpException 类,HttpException 构造函数采用两个必需的参数来确定响应

  • 该 response 参数定义 JSON 响应正文。它可以是 a string 或 an object ,如下所述
  • • 该 status 参数定义 HTTP 状态代码。nest提供了一个HttpStatus枚举

默认情况下,JSON 响应正文包含两个属性:

  • statusCode :默认为 status 参数中提供的 HTTP 状态代码
  • message :基于 status HTTP 错误的简短描述

若要仅覆盖 JSON 响应正文的消息部分,请在 response 参数中提供字符串。若要覆盖整个 JSON 响应正文,请在 response 参数中传递一个对象。Nest 将序列化对象并将其作为 JSON 响应正文返回。

Nest 提供了一组继承自 base HttpException 的标准异常:

  • BadRequestException
  • UnauthorizedException
  • NotFoundException
  • ForbiddenException
  • NotAcceptableException
  • RequestTimeoutException
  • ConflictException
  • GoneException
  • HttpVersionNotSupportedException
  • PayloadTooLargeException
  • UnsupportedMediaTypeException
  • UnprocessableEntityException
  • InternalServerErrorException
  • NotImplementedException
  • ImATeapotException
  • MethodNotAllowedException
  • BadGatewayException
  • ServiceUnavailableException
  • GatewayTimeoutException
  • PreconditionFailedException

使用:

throw new BadRequestException('Something bad happened');

自定义异常过滤器

定义:

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(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,
      });
  }
}

绑定:

@Post()
@UseFilters(new HttpExceptionFilter())
async create(@Body() createCatDto: CreateCatDto) {
  throw new ForbiddenException();
}

全局过滤器

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalFilters(new HttpExceptionFilter());
  await app.listen(3000);
}
bootstrap();

或:

import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';

@Module({
  providers: [
    {
      provide: APP_FILTER,
      useClass: HttpExceptionFilter,
    },
  ],
})
export class AppModule {}