在 Nest 里路由被“打散”到各个 Module 的 Controller 后,想一次性看清“我到底暴露了哪些 HTTP 接口”,官方标配:Swagger (@nestjs/swagger
)
1
2
| npm i @nestjs/swagger swagger-ui-express
# 如果用 fastify 就把 swagger-ui-express 换成 fastify-swagger
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| 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);
// 1. 基础信息
const config = new DocumentBuilder()
.setTitle('商城接口文档')
.setDescription('供 APP/小程序后台调用')
.setVersion('1.0.0')
.addBearerAuth() // 默认 JWT 认证按钮
.build();
// 2. 生成文档对象 & 挂载路由
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document); // 访问 http://localhost:3000/api
await app.listen(3000);
}
bootstrap();
|
启动后浏览器打开 http://localhost:3000/api
就能看到 “Swagger UI” 页面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| // cats/cats.controller.ts
import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';
import { CatsService } from './cats.service';
import { CreateCatDto } from './dto/create-cat.dto';
import { Cat } from './entities/cat.entity';
@ApiTags('猫咪') // 分组名
@Controller('cats')
export class CatsController {
constructor(private readonly catsService: CatsService) {}
@Post()
@ApiOperation({ summary: '新建一只猫' })
@ApiBody({ type: CreateCatDto })
@ApiResponse({ status: 201, description: '创建成功', type: Cat })
create(@Body() createCatDto: CreateCatDto) {
return this.catsService.create(createCatDto);
}
@Get(':id')
@ApiParam({ name: 'id', description: '猫咪ID', example: 42 })
@ApiResponse({ status: 200, description: '详情', type: Cat })
findOne(@Param('id') id: string) {
return this.catsService.findOne(+id);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| // cats/dto/create-cat.dto.ts
import { ApiProperty } from '@nestjs/swagger';
export class CreateCatDto {
@ApiProperty({ description: '猫咪名字', example: 'Kitty' })
name: string;
@ApiProperty({ description: '年龄', minimum: 0, maximum: 30, example: 2 })
age: number;
@ApiProperty({ description: '品种', required: false, example: '布偶' })
breed?: string;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // cats/entities/cat.entity.ts
export class Cat {
@ApiProperty({ example: 1, description: '主键' })
id: number;
@ApiProperty()
name: string;
@ApiProperty()
age: number;
@ApiProperty()
breed: string;
}
|
保存后 热重载,回到 http://localhost:3000/api
立即能看到:
分组 → 接口 → 参数表格 → Try it out → 发送请求 → 看到返回结果。
目的 | 注解 | 放在哪 |
---|
分组 | @ApiTags('用户') | 控制器类 |
接口标题/描述 | @ApiOperation({summary:'登录'}) | 方法 |
路径/查询/头参数 | @ApiParam @ApiQuery @ApiHeader | 方法 |
请求体 | @ApiBody({type:Dto}) | 方法 |
返回体 | @ApiResponse({status:200, type:Entity}) | 方法 |
隐藏接口 | @ApiExcludeEndpoint() | 方法 |
全局认证 | addBearerAuth() 已在 DocumentBuilder 配置 | 主文件 |
单个接口需认证 | @ApiBearerAuth() | 控制器或方法 |
1
2
3
| if (process.env.NODE_ENV !== 'production') {
SwaggerModule.setup('api', app, document);
}
|
或者再加一层 BasicAuth:
1
2
| import * as basicAuth from 'express-basic-auth';
app.use('/api', basicAuth({ users: { admin: '123456' }, challenge: true }));
|
- 接口多版本分组 –
addServer('/v1').addServer('/v2')
- 上传文件 –
@ApiConsumes('multipart/form-data')
+ @ApiBody({schema:{type:'object', properties:{file:{type:'string', format:'binary'}}}})
- 生成客户端 SDK – 把
/api-json
得到的 OpenAPI 文件丢给 openapi-generator-cli - 自动带枚举、最小最大值、正则 – 只要 DTO 里用
class-validator
,@IsEnum @Min @Max
等装饰器会自动同步到 Swagger UI。
照以上步骤,你就完成了:
“装包 → 配一次 → 写注解 → 看 UI → 发请求” 的完整闭环。
Happy coding!
kimi