概念
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
Nest 是用于构建高效且可伸缩Web应用程序的渐进式 Node.js 框架。
@nestjs/swagger 是为Nest定制的Swagger模块,用装饰器的方式来生成描述RESTful api的文档。
背景
为了自定义描述某个接口的响应,可以使用@ApiResponse(),示例代码如下:
@ApiResponse({ status: 403, description: 'Forbidden.'})
此外,为了方便与Nest内置的常见异常相对应,@nestjs/swagger封装了一系列常见的异常响应:
@ApiOkResponse()
@ApiCreatedResponse()
@ApiBadRequestResponse()
@ApiUnauthorizedResponse()
@ApiNotFoundResponse()
@ApiForbiddenResponse()
@ApiMethodNotAllowedResponse()
@ApiNotAcceptableResponse()
@ApiRequestTimeoutResponse()
@ApiConflictResponse()
@ApiGoneResponse()
@ApiPayloadTooLargeResponse()
@ApiUnsupportedMediaTypeResponse()
@ApiUnprocessableEntityResponse()
@ApiInternalServerErrorResponse()
@ApiNotImplementedResponse()
@ApiBadGatewayResponse()
@ApiServiceUnavailableResponse()
@ApiGatewayTimeoutResponse()
但是对于自定义的异常响应,还是需要用@ApiResponse()去实现,每次都要手写错误码和错误信息。
内容
基于能偷懒就绝不多干活的懒人理念,笔者封装了一个@ApiFailResponse()来实现根据自定义异常来描述异常响应。示例代码如下:
@ApiFailResponse({
type: ApiErrorException,
})
最终效果如下图:
我们可以看到只需要传入一个异常类,就可以把错误码和对应的描述在接口文档中呈现出来,一切都显得so easy。那么接下来,让我们看看ApiFailResponse的具体实现,代码如下:export const ApiFailResponse = (metadata: ResponseMetadata) => {
// 获取参数type中的异常类型,并实例化
const type: AppException = new metadata.type()
return ApiResponse({
...metadata,
status: type.getStatusCode(),
description: type.getMsg(),
})
}
Tip:ApiErrorException继承于AppException,AppException是笔者自己封装的异常类型,getStatusCode()方法可获取错误码,getMsg()可获取错误信息。
具体实现参考上篇文章《如何封装一个Nest风格的异常》
ApiFailResponse首先实例化一个异常,再获取异常的错误码和错误信息,赋值给status和description。用这种方式就把异常的错误码和错误信息暴露给Swagger接口文档。
尾声
在这里可能有人提出疑问,status的本意应该是指http状态码,而不是错误码。那么为什么不把错误和错误信息,都放到description中?这样status就还是能保持本意。
其实这是因为swagger在一个接口中,相同status只能描述一个响应。也就是说,我们无法同时描述两个status都为200的响应。所以这里才把错误码当做http状态码返回。其实问题也不大,接口文档最重要的是后端写的爽,前端看的明白就可以了。嗯,能偷懒就行。