NestJs - 异常过滤器

133 阅读1分钟

全局异常过滤器

NestJs 内置了一个全局异常过滤器,用来捕获标准异常,即 HttpException 类型异常(及其子类型)。如果捕获到的异常不是标准异常,那会返回默认 JSON 响应。

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

HttpException

HttpException 构造函数接收三个参数。

  1. response: 定义 JSON 响应主体。可以是 string 或 object。

    • string: 只覆盖 JSON 响应中的正文消息部分
    • object: 序列化该对象并作为响应主体返回。
  2. status: Http 状态码,最好使用 HttpStatus 枚举。

  3. options: 接收一个对象,参数为 cause。用于提供日志错误信息。

自定义异常

自定义异常就是基于 HttpException 基类的子类。在 NestJs 中,基本不需要自定义异常。

export class ForbiddenException extends HttpException {
  constructor() {
    super('Forbidden', HttpStatus.FORBIDDEN);
  }
}

内置标准异常

这些内置异常都继承自 HttpException。

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

自定义过滤器

自定以过滤器需要实现 ExceptionFilter 接口。

ExceptionFilter

ExceptionFilter 接口定义了一个泛型。所有异常过滤器都应实现通用 ExceptionFilter<T> 接口。T 为错误类型。 ExceptionFilter 接口要求你必须实现 catch 函数。该函数接收两个参数。

  • exception: 错误
  • host: ArgumentHost 对象

同时需要使用 @Catch 装饰器绑定元数据,定义该过滤器需要处理的异常的类型。如果不传参数,则会捕获所有的过滤器。

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,
      });
  }
}