Nest 集成 Swagger 文档很容易

# 安装 Swagger

h
$ npm install --save @nestjs/swagger swagger-ui-express

安装完成后,在 main.ts 文件中定义并初始化 SwaggerModule 类:

t
// 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();

alt swagger 文档

OK, 就是这么简单,现在可以访问 /api 就是 swagger 的文档了,只包括请求类型和接口 path , 如果需要详细的接口文档当然还需要补充一些其它详细内容

# Swagger 文档配置

# 显示请求参数及参数类型

目前有个 post options/set 接口,从文档上看不到请求的内容是什么

找到之前完成的 options.controller.tsoptionType 添加 @ApiProperty() 注解即可

t
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;
    }
}

再次打开文档,则会显示该接口的参数及参数类型,为了更详细点可以加入一点 descriptionrequired

t
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

t
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

t
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 接口文档了

alt swagger 文档

# 配置 API 多版本

标准的后端接口一般都有前缀,诸如 /api/user/xxx , 我们在所有控制器里都写 api 前缀也能达到目的,但显然有更方便的办法

# 添加统一接口前缀

添加统一前缀很方便,直接在 main.ts 里添加一行

t
const app = await NestFactory.create(AppModule);
app.setGlobalPrefix('api');// 统一前缀

即该应用下所有接口都有 api 前缀了

# 设置多个 API 版本号

随着项目的逐渐深入开发,接口会有修改,有时候会有多个版本的接口同时存在,那我们就要区分接口版本号了

常用的办法是在接口的前面加 v1 , 或者使用 HTTP header 来区分,Nest 也为我们准备好了这些配置

# 通过 URI 设置版本号

main.ts 中加入如下代码

t
app.enableVersioning({
  type: VersioningType.URI,
});

同时在 controller 中也要声明哪些是 version 1 的,哪些是 version 2 的

t
// 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

alt swagger 文档

# 通过 http header 设置版本号

加入如下代码代表采用 header 方式区分版本号

t
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 文档

请我喝杯[咖啡]~( ̄▽ ̄)~*

一个放羊娃 微信支付

微信支付

一个放羊娃 支付宝

支付宝