iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 26
0
Modern Web

讀官網文件邊走邊學nest.js系列 第 26

Day26 用Nestjs Decorator建立Swagger API Doc

在nestjs下可以用類似ASP.net core或是Java中類似的reflection機制方式,利用Decorators及Swagger Module自動產生API文件頁面。

安裝套件

yarn add @nestjs/swagger

產生最簡單的Swagger API說明頁面

在main.ts下,加入產生Swagger頁面的程式碼

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
    
  // 建立Swagger頁面設定檔  
  const userApiOptions = new DocumentBuilder()
            .setTitle('User API Doc')
            .setDescription('User API Info')
            .setVersion('1.0')
            .addBearerAuth()
            .addTag('users') // match tags in controllers
            .build();
  
  // 沒有指定第三個參數代表所有Module的controller都會被偵測
  const userApiDocument= SwaggerModule.createDocument(app, userApiOptions);
  // 指定Swagger API頁面路徑及傳入nest app及頁面設定檔
  SwaggerModule.setup('v1/api/', app, userApiDocument);

  await app.listen(3000);
  
}
bootstrap();

啟動nestjs

可以看到Parameter底下UserDTO沒有相關資訊

設定Swagger物件參數

傳遞物件參數包含@Body、@Query所參考到的物件,如UserDTO、userQueryDTO,要在Swagger頁面顯示物件資訊,透過@ApiModelProperty

userDTO.ts

export class UserDTO {
    @ApiModelProperty({
        maxLength:10,
        description:'Username'
    })
    ...
    username: string;

    @ApiModelProperty({
        uniqueItems: true,
        description:'Email',
        maxLength: 100
    })
    ...
    email: string;
    
    @ApiModelProperty()
    ...
    depId: number;

    @ApiModelProperty({required: false})
    ...
    roleIds: number[];
}


userQueryDTO

export class UserQueryDTO{
    
    @ApiModelProperty({
        description:'username keyword',
    })
    @IsString()
    name: string;
    
    @ApiModelProperty({
        description:'Page No',
        default:1,
    })
    @IsNumber({})
    page: number;

    @ApiModelProperty({
        description:'Records Per Page',
        default:5,
    })
    @IsNumber()
    pageSize: number;
}

Http Reponse回傳訊息

不同Http回應的code顯示訊息,透過@ApiOkResponse、@ApiCreatedResponse等來套用在controller下對應的方法,詳細@ApixxResponse清單上官網查詢

以user.controller為例

@ApiUseTags('users')
@ApiBearerAuth()
@ApiForbiddenResponse({description:'Unauthorized'})
@UseGuards(AuthGuard())
@Controller('users')
export class UsersController {
    constructor(
        private usersService: UsersService,
    ){}

  @ApiOkResponse({description:'Return Users Array'})
  @Get()
  userList(@Query() query: UserQueryDTO){
    return this.usersService.getUsers(query);
  }

  ...

  @Post()
  // 回傳201的療術
  @ApiCreatedResponse({description:'User Created'})
  // 回傳Internal Error的描述
  @ApiInternalServerErrorResponse({description:'Invalid Input'})
  @UsePipes(UserDTOValidationPipe)
  @ReflectMetadata('roles', ['admin', 'superuser'])
  create(@Body() userDTO: UserDTO){
    //throw new HttpException('糟糕!您的要求有問題,請洽系統管理員', HttpStatus.BAD_REQUEST);
    return this.usersService.addUser(userDTO);
    //return this.userRepo.createAndSave(userDTO); not work
  }

可以根據Exeception Filter顯示的message來設定Error類的Response的描述

以Module來區分Swagger頁面

Swagger Module是依據Module來區分頁面,現在的專案下,只有UserModule跟AuthModule,可以用不同路徑來區分

main.ts

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const userApiOptions = new DocumentBuilder()
            .setTitle('User API Doc')
            .setDescription('User API Info')
            .setVersion('1.0')
            .addBearerAuth()
            .addTag('users') // match tags in controllers
            .build();

  const userApiDocument= SwaggerModule.createDocument(app, userApiOptions, {include: [UserModule]});
  SwaggerModule.setup('v1/api/user', app, userApiDocument);

  const authApiOptions = new DocumentBuilder()
            .setTitle('Auth API Doc')
            .setDescription('Auth API Info')
            .setVersion('1.0')
            .addBearerAuth()
            .addTag('auth') // match tags in controllers
            .build();
  const authApiDocument= SwaggerModule.createDocument(app, authApiOptions, {include: [AuthModule]});
  SwaggerModule.setup('v1/api/auth', app, authApiDocument);

  await app.listen(3000);
  
}
bootstrap();


Auth API獨立另外一個頁面

Github Source Code


上一篇
Day25 JSON Web Token(JWT)保護API Endpoint-使用Passport
下一篇
Day27 存取env變數使用dotenv-儲存敏感資訊
系列文
讀官網文件邊走邊學nest.js31

尚未有邦友留言

立即登入留言