*由于最近新版@nestjs/swagger4.*的更新,使用的注解也发生了一些改动,具体可以查看
@nestjs/swagger官方地址
RESTful API
。Nest提供了专用的模块来使用它yarn add @nestjs/swagger swagger-ui-express --save
yarn add @nestjs/swagger fastify-swagger --save
// main.ts 中配置
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
// api文档插件
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// DocumentBuilder是一个辅助类,有助于结构的基本文件SwaggerModule。它包含几种方法,可用于设置诸如标题,描述,版本等属性。
const options = new DocumentBuilder()
.setTitle('nest入门接口标题')
.setDescription('使用nest书写的常用性接口') // 文档介绍
.setVersion('1.0.0') // 文档版本
.addTag('用户,安全') // 每个tag标签都可以对应着几个@ApiUseTags('用户,安全') 然后被ApiUseTags注释,字符串一致的都会变成同一个标签下的
// .setBasePath('http://localhost:5000')
.build();
// 为了创建完整的文档(具有定义的HTTP路由),我们使用类的createDocument()方法SwaggerModule。此方法带有两个参数,分别是应用程序实例和基本Swagger选项。
const document = SwaggerModule.createDocument(app, options);
// 最后一步是setup()。它依次接受(1)装入Swagger的路径,(2)应用程序实例, (3)描述Nest应用程序的文档。
SwaggerModule.setup('/api', app, document);
await app.listen(5000);
然后返回正确的状态和数据,文档都无需自己手写,减少不少的文档编辑量
定义控制器时,SwaggerModule寻找所有的使用@Body(),@Query()以及@Param()在路由处理器装饰。因此,可以创建有效的文档。
// user.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {
public getUser(id: string): string {
return `用户的id:${id}`;
}
}
// user.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { UserService } from './user.service';
@Controller('/user')
export class UserController {
constructor(private userService: UserService) { }
@Get('/get/:id')
public getUser(@Param('id') id: string): string {
return this.userService.getUser(id);
}
}
// user.module.ts
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
@Module({
providers: [UserService],
controllers: [UserController],
})
export class UserModule { }
// user.controller.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { UserController } from './user.controller';
import { UserService } from './user.service';
describe('UserController', () => {
let userController: UserController;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [UserController],
providers: [UserService],
}).compile();
userController = app.get<UserController>(UserController);
});
describe('user', () => {
it('should return "用户的id: xxx"', () => {
expect(userController.getUser('111')).toBe('用户的id:111');
});
});
});
swagger的配置装饰器都是以@api开头
import { ApiTags } from '@nestjs/swagger';
import { Controller, Get, Query } from '@nestjs/common';
@ApiTags('用户,安全')
@Controller('/user')
export class UserController {
//...
}
除了ApiImplicitHeaders之外,其它的接收一个对象,对象类型如下:
name: string; // 该数据的名称,比如:id可以写用户id或者id
description?: string; // 简介
required?: boolean; // 是否是必须的
type?: any; // 类型
isArray?: boolean; // 是否是数组
enum?: SwaggerEnumType; // 枚举类型
collectionFormat?: "csv" | "ssv" | "tsv" | "pipes" | "multi";
name: string;
description?: string;
required?: boolean;
修改user.controller.ts文件成如下代码:
import { Controller, Get, Param, Query } from '@nestjs/common';
import { ApiTags, ApiParam, ApiQuery, ApiHeader } from '@nestjs/swagger';
import { UserService } from './user.service';
@ApiTags('用户,安全')
@Controller('/user')
export class UserController {
constructor(private userService: UserService) { }
@Get('/get/:id')
@ApiParam({
name: 'id',
description: '这是用户id',
})
@ApiQuery({
name: 'role',
description: '这是需要传递的参数',
})
@ApiHeader({
name: 'authoriation',
required: true,
description: '本次请求请带上token',
})
public getUser(@Param('id') id: string, @Query('role') role: string): string {
return this.userService.getUser(id);
}
}
会发现变成,对应的字段有对应的描述信息
我们只需要在编写接口的同时添加swagger提供装饰器即可,无需开发过后再回来编写文档
// user.controller.ts 加上如下方法
@Post('/add')
public addUser(@Body() user: User) {
return user;
}
// User.ts
import { ApiProperty } from '@nestjs/swagger';
export class User {
@ApiProperty({
description: '用户名',
})
username: string;
@ApiProperty({
description: '密码',
})
password: string;
}
https://docs.nestjs.com/recipes/swagger
当参数是数组的情况下,我们可以这样配置@ApiProperty({ type: [String] })
@ApiResponse({ status: 401, description: '权限不足'})
@Post('/add')
public addUser(@Body() user: User) {
return user;
}
nestjs还内置了大量的相关http状态码的描述,具体可以参照官方
https://docs.nestjs.com/recipes/swagger
例如在addUser方法加上该装饰器
@ApiResponse({ status: 401, description: '权限不足'})
@ApiImplicitFile({
name: '头像',
description: '上传头像',
required: false,
})
@Post('/add')
public addUser(@Body() user: User) {
return user;
}
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';
import { UserModule } from './user/user.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const options = new DocumentBuilder()
.setTitle('用户信息文档')
.setDescription('用于用户信息的增删改查')
.setVersion('1.0')
.addTag('用户,安全')
.build();
const userDocument = SwaggerModule.createDocument(app, options, {
include: [UserModule], // 包含的模块
});
SwaggerModule.setup('api/user', app, userDocument);
const secondOptions = new DocumentBuilder()
.setTitle('整体文档')
.setDescription('包含了测试文档和前台应用文档')
.setVersion('1.0')
.addTag('用户,安全')
.build();
const appDocument = SwaggerModule.createDocument(app, secondOptions, {
include: [AppModule, UserModule],
});
SwaggerModule.setup('api', app, appDocument);
await app.listen(3000);
}
bootstrap();