Nest.js 内置 HTTP 异常笔记
侧边栏壁纸
  • 累计撰写 12 篇文章
  • 累计收到 1 条评论

Nest.js 内置 HTTP 异常笔记

ASN__
2026-02-24 / 0 评论 / 7 阅读 / 正在检测是否收录...

Nest.js 内置 HTTP 异常笔记

一、核心概念

Nest.js 从 @nestjs/common 导出的所有内置 HTTP 异常均继承自 HttpException 基类,每个异常对应标准的 HTTP 状态码,用于在控制器/服务中快速抛出符合 RESTful 规范的错误响应,无需手动拼接状态码和响应格式。

二、完整内置异常列表(含状态码+使用场景)

异常类名HTTP 状态码核心使用场景
BadRequestException400请求参数错误、格式非法(如参数校验失败)
UnauthorizedException401未认证(如无 token、token 无效/过期)
NotFoundException404资源不存在(如查询 ID 不存在的用户/文章)
ForbiddenException403已认证但无权限操作(如普通用户访问管理员接口)
NotAcceptableException406服务器无法生成客户端请求的内容格式(如客户端要求 XML 但仅支持 JSON)
RequestTimeoutException408请求超时(如客户端请求未在指定时间内完成)
ConflictException409资源冲突(如创建已存在的用户名、重复提交表单)
GoneException410资源永久删除(如已下架的商品,无法恢复)
HttpVersionNotSupportedException505不支持的 HTTP 协议版本(如客户端用 HTTP/3 但服务器仅支持 HTTP/1.1)
PayloadTooLargeException413请求体过大(如上传文件超过服务器限制)
UnsupportedMediaTypeException415不支持的媒体类型(如上传图片时 Content-Type 为 text/plain)
UnprocessableEntityException422请求体格式正确但语义错误(如手机号格式正确但非合法号码)
InternalServerErrorException500服务器内部错误(如代码逻辑异常、数据库连接失败)
NotImplementedException501接口未实现(如规划中的接口暂未开发)
ImATeapotException418趣味异常(RFC 2324 定义,实际极少使用,可用于测试)
MethodNotAllowedException405请求方法不允许(如 GET 访问仅支持 POST 的接口)
BadGatewayException502网关错误(如 Nest 作为网关转发请求时,后端服务返回无效响应)
ServiceUnavailableException503服务不可用(如服务器维护、过载,暂时无法处理请求)
GatewayTimeoutException504网关超时(如 Nest 转发请求时,后端服务响应超时)
PreconditionFailedException412前置条件失败(如请求头中 If-Match 与服务器资源版本不匹配)

三、基础使用方式

1. 最简使用(仅指定错误消息)
import { Controller, Get, NotFoundException } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get(':id')
  findOne(@Param('id') id: string) {
    const user = null; // 模拟查询不到用户
    if (!user) {
      // 仅指定消息,error 字段会默认显示 HTTP 状态码对应的默认描述(如 "Not Found")
      throw new NotFoundException(`User with ID ${id} not found`);
    }
    return user;
  }
}

响应结果

{
  "message": "User with ID 123 not found",
  "error": "Not Found",
  "statusCode": 404
}
2. 完整使用(指定消息+原因+描述)
import { Controller, Post, BadRequestException } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Post()
  create(@Body() createUserDto: any) {
    try {
      // 模拟参数校验失败
      if (!createUserDto.username) {
        throw new Error('Username is required');
      }
    } catch (error) {
      throw new BadRequestException('Failed to create user', {
        cause: error, // 原始错误(用于日志排查,不会返回给客户端)
        description: 'Username is a mandatory field', // 客户端可见的详细描述
      });
    }
  }
}

响应结果

{
  "message": "Failed to create user",
  "error": "Username is a mandatory field",
  "statusCode": 400
}

四、进阶用法:自定义 HTTP 异常

若内置异常无法满足需求(如自定义状态码/响应格式),可继承 HttpException 实现自定义异常:

import { HttpException, HttpStatus } from '@nestjs/common';

// 自定义异常:请求频率过高(429 状态码)
export class TooManyRequestsException extends HttpException {
  constructor(message: string = 'Too many requests', description?: string) {
    super(
      {
        message,
        error: description || 'Too Many Requests',
        statusCode: HttpStatus.TOO_MANY_REQUESTS, // 429
      },
      HttpStatus.TOO_MANY_REQUESTS,
    );
  }
}

// 使用自定义异常
@Controller('api')
export class ApiController {
  @Get()
  getData() {
    throw new TooManyRequestsException('请求过于频繁', '请等待 60 秒后重试');
  }
}

响应结果

{
  "message": "请求过于频繁",
  "error": "请等待 60 秒后重试",
  "statusCode": 429
}

五、全局异常过滤器(统一响应格式)

实际开发中,通常会自定义全局异常过滤器,统一所有 HTTP 异常的响应格式(如增加 timestamp 字段):

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { 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 status = exception.getStatus();
    const exceptionResponse = exception.getResponse() as { message: string; error: string };

    response.status(status).json({
      code: status, // 自定义码段
      msg: exceptionResponse.message,
      detail: exceptionResponse.error,
      timestamp: new Date().toISOString(), // 错误时间
      path: ctx.getRequest().url, // 请求路径
    });
  }
}

// 在 main.ts 注册全局过滤器
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './filters/http-exception.filter';

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

统一后的响应示例

{
  "code": 400,
  "msg": "Something bad happened",
  "detail": "Some error description",
  "timestamp": "2026-02-24T10:00:00.000Z",
  "path": "/users"
}

总结

  1. Nest 内置 HTTP 异常覆盖了所有常见 HTTP 状态码,每个异常对应明确的业务场景,可直接抛出无需手动处理状态码;
  2. 内置异常支持自定义 messagecause(日志用)和 description(客户端可见),兼顾排查和用户体验;
  3. 若内置异常不满足需求,可继承 HttpException 实现自定义异常,或通过全局过滤器统一响应格式。
1

评论

博主关闭了所有页面的评论