You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

@nestjs/swagger CLI插件仅识别成功响应,失败响应未显示

问题原因

@nestjs/swagger的CLI插件是基于控制器方法的返回类型注解和Nest默认的HTTP响应规则自动生成接口文档的。你的控制器方法标注返回Promise<ResponseDto>,插件只会将这个类型映射到默认的200状态码响应,它无法解析Service层try/catch逻辑里返回的不同statusCode值,自然没法推断出500等失败状态的响应。

解决方案

以下是几种不需要给每个控制器手动添加@ApiResponse装饰器的方案:

方案1:自定义异常过滤器 + 异常类型推断(推荐)

放弃在Service里返回带错误状态码的ResponseDto,改为抛出自定义异常,再通过全局异常过滤器统一转换成你需要的ResponseDto格式。CLI插件会自动识别方法可能抛出的异常类型,并生成对应的响应状态码。

步骤1:定义自定义异常

// src/common/exceptions/custom.exception.ts
import { HttpException, HttpStatus } from '@nestjs/common';
import { ApiProperty } from '@nestjs/swagger';

export class CustomHttpException extends HttpException {
  @ApiProperty({ description: '错误信息' })
  message: string;

  @ApiProperty({ description: '错误状态码' })
  statusCode: number;

  constructor(message: string, statusCode: HttpStatus) {
    super(message, statusCode);
    this.message = message;
    this.statusCode = statusCode;
  }
}

步骤2:全局异常过滤器

// src/common/filters/http-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Response } from 'express';
import { CustomHttpException } from '../exceptions/custom.exception';

@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();

    let responseBody: { statusCode: number; body: { message: string; data: any } };

    if (exception instanceof CustomHttpException) {
      responseBody = {
        statusCode: exception.statusCode,
        body: {
          message: exception.message,
          data: null,
        },
      };
    } else {
      const errorResponse = exception.getResponse();
      responseBody = {
        statusCode: status,
        body: {
          message: typeof errorResponse === 'string' ? errorResponse : (errorResponse as any).message,
          data: null,
        },
      };
    }

    response.status(status).json(responseBody);
  }
}

步骤3:修改Service层逻辑,抛出异常

// merchant.service.ts
import { Injectable, HttpStatus } from '@nestjs/common';
import { Merchant } from './entities/merchant.entity';
import { CustomHttpException } from '../../common/exceptions/custom.exception';
import { ResponseDto } from '../../response.dto';

@Injectable()
export class MerchantService {
  async findOne(merchantId: string): Promise<ResponseDto> {
    try {
      const { Item } = await Merchant.get({ merchantId: merchantId });
      console.log("Retrieved table entries, ", Item);
      return { statusCode: 200, body: { message: "", data: Item } };
    } catch(err) {
      console.log(err);
      // 抛出自定义异常
      throw new CustomHttpException("ERROR.", HttpStatus.INTERNAL_SERVER_ERROR);
    }    
  }
}

步骤4:全局注册异常过滤器

在main.ts中注册:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './common/filters/http-exception.filter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 注册全局异常过滤器
  app.useGlobalFilters(new HttpExceptionFilter());
  await app.listen(3000);
}
bootstrap();

这样CLI插件会自动识别到控制器方法可能抛出CustomHttpException,并在Swagger文档中生成对应的500状态码响应,同时全局过滤器保证返回格式和你原来的ResponseDto一致。

方案2:全局装饰器批量添加通用响应

如果不想修改现有Service逻辑,可以编写一个全局装饰器,自动为所有控制器接口添加常见的失败响应(如401、500等),只需全局注册一次,无需每个控制器手动添加。

实现全局装饰器

// src/common/decorators/global-api-responses.decorator.ts
import { applyDecorators } from '@nestjs/common';
import { ApiResponse } from '@nestjs/swagger';
import { ResponseDto } from '../../response.dto';

export function GlobalApiResponses() {
  return applyDecorators(
    ApiResponse({ status: 401, description: '未授权' }),
    ApiResponse({ status: 500, description: '服务器内部错误', type: ResponseDto }),
    // 可添加更多通用失败状态码
  );
}

全局注册装饰器

在main.ts中通过Swagger文档构建器全局添加:

import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

async function bootstrap() {
  // ...其他初始化代码
  const config = new DocumentBuilder()
    .setTitle('API文档')
    .setDescription('API接口描述')
    .setVersion('1.0')
    .build();
  const document = SwaggerModule.createDocument(app, config, {
    extraModels: [ResponseDto],
    operationFactory: (operationKey, operationDescriptor) => {
      const operation = SwaggerModule.createOperation(operationKey, operationDescriptor);
      // 批量添加通用失败响应
      operation.responses['401'] = { description: '未授权' };
      operation.responses['500'] = { 
        description: '服务器内部错误', 
        content: {
          'application/json': { schema: { $ref: '#/components/schemas/ResponseDto' } }
        }
      };
      return operation;
    },
  });
  SwaggerModule.setup('api', app, document);
}

这种方式无需修改业务代码,直接在Swagger文档构建阶段批量添加通用响应。


内容的提问来源于stack exchange,提问作者Sa'id Kharboutli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:51:09