Nest 集成 Swagger 文档很容易
# 安装 Swagger
$ npm install --save @nestjs/swagger swagger-ui-express |
安装完成后,在 main.ts
文件中定义并初始化 SwaggerModule
类:
// main.ts | |
import { NestFactory } from '@nestjs/core'; | |
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; | |
import { AppModule } from './app.module'; | |
async function bootstrap() { | |
const app = await NestFactory.create(AppModule); | |
const config = new DocumentBuilder() | |
.setTitle('管理系统API文档') | |
.setDescription('管理系统API文档') | |
.setVersion('0.0.1') | |
.addTag('api') | |
.build(); | |
const document = SwaggerModule.createDocument(app, config); | |
SwaggerModule.setup('api', app, document); | |
await app.listen(9000); | |
console.log("server listen on 9000!"); | |
} | |
bootstrap(); |
OK, 就是这么简单,现在可以访问 /api
就是 swagger 的文档了,只包括请求类型和接口 path
, 如果需要详细的接口文档当然还需要补充一些其它详细内容
# Swagger 文档配置
# 显示请求参数及参数类型
目前有个 post options/set
接口,从文档上看不到请求的内容是什么
找到之前完成的 options.controller.ts
将 optionType
添加 @ApiProperty()
注解即可
import { Controller,Get,Post,Body } from '@nestjs/common'; | |
import { Options } from "./entity/options.entity"; | |
import { OptionsService } from "./options.service"; | |
import { ApiProperty } from '@nestjs/swagger'; | |
class optionType { | |
@ApiProperty() | |
key:string; | |
@ApiProperty() | |
value:string; | |
@ApiProperty() | |
prefix:string|null | |
} | |
@Controller('options') | |
export class OptionsController { | |
constructor( | |
private readonly optionsService: OptionsService, | |
) {} | |
@Get() | |
async getAllOptions():Promise<Options[]>{ | |
return await this.optionsService.getAll(); | |
} | |
@Post("set") | |
async setOption(@Body() data:optionType):Promise<Options>{ | |
let option = await this.optionsService.getOne(data.key); | |
// 存在则修改,不存在新增 | |
if(option){ | |
await this.optionsService.update(option,data.value); | |
}else{ | |
option = await this.optionsService.add(data); | |
} | |
return option; | |
} | |
} |
再次打开文档,则会显示该接口的参数及参数类型,为了更详细点可以加入一点 description
或 required
class optionType { | |
@ApiProperty({ | |
description: '全局配置项key', | |
required: true, | |
default: "example", | |
}) | |
key:string; | |
@ApiProperty({ | |
description: '全局配置项value', | |
required: true, | |
default: "exampleValue", | |
}) | |
value:string; | |
@ApiProperty({ | |
description: '全局配置项前缀', | |
required:false, | |
default: "", | |
}) | |
prefix:string|null | |
} |
# 显示响应参数及参数类型
请求参数有了,那么响应参数也应该有
相对应的,响应参数使用 @ApiResponse
注解,同时需要在 response 的类型上加 @ApiProperty
, 对应地就是在 entity
改动后的 options.entity.ts
import {Entity, Column, PrimaryGeneratedColumn,Index} from 'typeorm'; | |
import {ApiProperty} from "@nestjs/swagger"; | |
@Entity("options") | |
export class Options { | |
@PrimaryGeneratedColumn({ | |
unsigned:true, | |
}) | |
@ApiProperty({default:1}) | |
id: number; | |
@Index() | |
@ApiProperty() | |
@Column({ | |
type: "varchar", | |
length: 255, | |
default: "", | |
comment: "配置key" | |
}) | |
key: string; | |
@ApiProperty() | |
@Column({ | |
type: "varchar", | |
length: 2000, | |
default: "", | |
comment: "配置值" | |
}) | |
value: string; | |
@ApiProperty() | |
@Index() | |
@Column({ | |
type: "varchar", | |
length: 255, | |
default: "", | |
comment: "配置前缀" | |
}) | |
prefix: string; | |
} |
改动后的 options.controller.ts
import { Controller,Get,Post,Body } from '@nestjs/common'; | |
import { Options } from "./entity/options.entity"; | |
import { OptionsService } from "./options.service"; | |
import { ApiProperty,ApiTags,ApiResponse } from '@nestjs/swagger'; | |
class optionType { | |
@ApiProperty({ | |
description: '全局配置项key', | |
required: true, | |
default: "example", | |
}) | |
key:string; | |
@ApiProperty({ | |
description: '全局配置项value', | |
required: true, | |
default: "exampleValue", | |
}) | |
value:string; | |
@ApiProperty({ | |
description: '全局配置项前缀', | |
required:false, | |
default: "", | |
}) | |
prefix:string|null | |
} | |
@ApiTags('options') | |
@ApiResponse({ status: 400, description: '数据库错误'}) | |
@Controller('options') | |
export class OptionsController { | |
constructor( | |
private readonly optionsService: OptionsService, | |
) {} | |
@Get() | |
@ApiResponse({ status: 201, description: '响应成功,返回options列表',type:[Options]}) | |
async getAllOptions():Promise<Options[]>{ | |
return await this.optionsService.getAll(); | |
} | |
@Post("set") | |
@ApiResponse({ status: 201, description: '响应成功,返回options',type:Options}) | |
async setOption(@Body() data:optionType):Promise<Options>{ | |
let option = await this.optionsService.getOne(data.key); | |
// 存在则修改,不存在新增 | |
if(option){ | |
await this.optionsService.update(option,data.value); | |
}else{ | |
option = await this.optionsService.add(data); | |
} | |
return option; | |
} | |
} |
现在刷新一下,则会看到更详细的 api 接口文档了
# 配置 API 多版本
标准的后端接口一般都有前缀,诸如 /api/user/xxx
, 我们在所有控制器里都写 api 前缀也能达到目的,但显然有更方便的办法
# 添加统一接口前缀
添加统一前缀很方便,直接在 main.ts
里添加一行
const app = await NestFactory.create(AppModule); | |
app.setGlobalPrefix('api');// 统一前缀 |
即该应用下所有接口都有 api
前缀了
# 设置多个 API 版本号
随着项目的逐渐深入开发,接口会有修改,有时候会有多个版本的接口同时存在,那我们就要区分接口版本号了
常用的办法是在接口的前面加 v1
, 或者使用 HTTP header
来区分,Nest 也为我们准备好了这些配置
# 通过 URI 设置版本号
在 main.ts
中加入如下代码
app.enableVersioning({ | |
type: VersioningType.URI, | |
}); |
同时在 controller
中也要声明哪些是 version 1 的,哪些是 version 2 的
// app.controller.ts | |
import {Controller, Get} from '@nestjs/common'; | |
import {AppService} from './app.service'; | |
import {HttpService} from '@nestjs/axios'; | |
import {ConfigService} from "nestjs-config"; | |
import {Version} from "@nestjs/common"; | |
@Controller() | |
export class AppController { | |
@Get() | |
@Version('1') | |
getHello(): string { | |
return "hello world!"; | |
} | |
@Get() | |
@Version('2') | |
getHelloCn(): string { | |
return "你好世界!"; | |
} | |
} |
可以看到接口自动添加了 v1
, v2
# 通过 http header 设置版本号
加入如下代码代表采用 header 方式区分版本号
app.enableVersioning({ | |
type: VersioningType.HEADER, | |
header: 'ApiVersion', | |
}); |
这样的话,我们请求接口的时候就必须要加 header 了,不然接口会报 404
文档里没有地方展现该 header, 可以通过添加 @ApiHeader
到控制器上
import {Controller, Get} from '@nestjs/common'; | |
import {AppService} from './app.service'; | |
import {HttpService} from '@nestjs/axios'; | |
import {ConfigService} from "nestjs-config"; | |
import {Version} from "@nestjs/common"; | |
import {ApiHeader} from "@nestjs/swagger"; | |
@Controller() | |
export class AppController { | |
@Get("hello") | |
@ApiHeader({required:true,name:"ApiVersion",enum:["1","2"],description:"请选择一个版本"}) | |
@Version('1') | |
getHello(): string { | |
return "hello world!"; | |
} | |
@Get("hello") | |
@ApiHeader({required:true,name:"ApiVersion",enum:["1","2"],description:"请选择一个版本"}) | |
@Version('2') | |
getHelloCn(): string { | |
return "你好世界!"; | |
} | |
} |
至此,我们多版本 API 也配置好了.
Swagger 更多配置项和注解见 Nest 文档