OpenAPI (Swagger)

OpenAPI (Swagger)

This chapter applies only to TypeScript

OpenAPI (Swagger) 사양은 RESTful API를 설명하는 강력한 정의 형식입니다. Nest는 전용 모듈을 제공합니다.

Installation

먼저 필요한 패키지를 설치해야합니다.

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

fastify를 사용하는 경우 swagger-ui-express 대신 fastify-swagger를 설치해야합니다.

$ npm install --save @nestjs/swagger fastify-swagger

Bootstrap

설치 프로세스가 완료되면 부트 스트랩 파일 (대부분 main.ts)을 열고 SwaggerModule 클래스를 사용하여 Swagger를 초기화 하십시오.

import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { ApplicationModule } from './app.module';

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

  const options = new DocumentBuilder()
    .setTitle('Cats example')
    .setDescription('The cats API description')
    .setVersion('1.0')
    .addTag('cats')
    .build();
  const document = SwaggerModule.createDocument(app, options);
  SwaggerModule.setup('api', app, document);

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

DocumentBuilderSwaggerModule의 기본 문서를 구성하는 데 도움을 주는 헬퍼 클래스입니다. 제목, 설명, 버전 등과 같은 속성을 설정할 수있는 몇가지 방법이 포함되어 있습니다.

정의된 HTTP 경로로 전체 문서를 만들려면 SwaggerModule 클래스의 createDocument()메소드를 사용하십시오. 이 메소드는 각각 응용 프로그램 인스턴스와 기본 Swagger 옵션의 두가지 인수를 사용합니다.

마지막 단계는 setup()을 호출하는 것입니다. (1) Swagger를 장착하는 경로, (2) 응용 프로그램 인스턴스, (3) Nest 애플리케이션을 설명하는 문서를 순차적으로 허용합니다.

이제 다음 명령을 실행하여 HTTP 서버를 시작할 수 있습니다.

$ npm run start

응용 프로그램이 실행되는 동안 브라우저를 열고 http://localhost:3000/api로 이동하십시오. 비슷한 페이지가 나타납니다.

SwaggerModule은 모든 엔드 포인트를 자동으로 반영합니다. 백그라운드에서는 swagger-ui-express를 사용하고 라이브 문서를 만듭니다.

info 힌트 해당 Swagger JSON 파일을 다운로드하려면 브라우저에서http://localhost:3000/api-json을 호출하면됩니다 (Swagger 설명서가 http://localhost:3000/api에 게시된 경우). ).

Body, query, path parameters

정의된 컨트롤러를 검사하는 동안 SwaggerModule은 경로 핸들러에서 사용된 @Body(), @Query()@Param()데코레이터를 모두 찾습니다. 따라서 유효한 문서를 만들 수 있습니다.

또한 이 모듈은 리플렉션을 활용하여 모델 정의를 만듭니다. 다음 코드를 살펴보십시오.

@Post()
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}

warning 알림 본문 정의를 암시적으로 설정하려면 @ApiImplicitBody() 데코레이터 (@nestjs/swagger 패키지)를 사용할 수 있습니다.

CreateCatDto를 기반으로 모듈 정의가 생성됩니다 :

보시다시피 클래스에 선언된 속성이 몇 개 있지만 정의가 비어 있습니다. 클래스 속성이 SwaggerModule에 액세스할 수 있도록 하려면, @ApiModelProperty() 데코레이터로 모든 속성을 표시해야 합니다.

import { ApiModelProperty } from '@nestjs/swagger';

export class CreateCatDto {
  @ApiModelProperty()
  readonly name: string;

  @ApiModelProperty()
  readonly age: number;

  @ApiModelProperty()
  readonly breed: string;
}

브라우저를 열고 생성 된 CreateCatDto 모델을 확인하십시오 :

@ApiModelProperty() 데코레이터는 옵션 객체를 받습니다 :

export const ApiModelProperty: (metadata?: {
  description?: string;
  required?: boolean;
  type?: any;
  isArray?: boolean;
  collectionFormat?: string;
  default?: any;
  enum?: SwaggerEnumType;
  format?: string;
  multipleOf?: number;
  maximum?: number;
  exclusiveMaximum?: number;
  minimum?: number;
  exclusiveMinimum?: number;
  maxLength?: number;
  minLength?: number;
  pattern?: string;
  maxItems?: number;
  minItems?: number;
  uniqueItems?: boolean;
  maxProperties?: number;
  minProperties?: number;
  readOnly?: boolean;
  xml?: any;
  example?: any;
}) => PropertyDecorator;

warning 힌트 {{"@ApiModelProperty({ required: false })"}}를 계속 입력하지 않도록 하는@ApiModelPropertyOptional()단축 데코레이터가 있습니다.

덕분에 default 값을 간단히 설정하고 속성이 필요한지 여부를 결정하거나 유형을 명시적으로 설정할 수 있습니다.

Multiple specifications

Swagger 모듈은 또한 여러 사양을 지원하는 방법을 제공합니다. 즉, 엔드 포인트마다 다른 SwaggerUI를 사용하여 다른 문서를 제공할 수 있습니다.

SwaggerModule이 다중 사양을 지원할 수 있도록 하려면 응용 프로그램을 모듈 방식으로 작성해야 합니다. createDocument()메소드는 세 번째 인수인 extraOptions를 사용합니다. extraOptionsinclude 속성이 모듈 배열을 필요로 하는 객체입니다.

아래와 같이 다중 사양 지원을 설정할 수 있습니다.

import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { ApplicationModule } from './app.module';

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

  /**
   * createDocument(application, configurationOptions, extraOptions);
   *
   * createDocument method takes in an optional 3rd argument "extraOptions"
   * which is an object with "include" property where you can pass an Array
   * of Modules that you want to include in that Swagger Specification
   * E.g: CatsModule and DogsModule will have two separate Swagger Specifications which
   * will be exposed on two different SwaggerUI with two different endpoints.
   */

  const options = new DocumentBuilder()
    .setTitle('Cats example')
    .setDescription('The cats API description')
    .setVersion('1.0')
    .addTag('cats')
    .build();

  const catDocument = SwaggerModule.createDocument(app, options, {
    include: [CatsModule],
  });
  SwaggerModule.setup('api/cats', app, catDocument);

  const secondOptions = new DocumentBuilder()
    .setTitle('Dogs example')
    .setDescription('The dogs API description')
    .setVersion('1.0')
    .addTag('dogs')
    .build();

  const dogDocument = SwaggerModule.createDocument(app, secondOptions, {
    include: [DogsModule],
  });
  SwaggerModule.setup('api/dogs', app, dogDocument);

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

이제 다음 명령으로 서버를 시작할 수 있습니다.

$ npm run start

Cat의 SwaggerUI를 보려면 http://localhost:3000/api/cats로 이동하십시오.

http://localhost:3000/api/dogs는 강아지를위한 SwaggerUI를 노출시킵니다:

warning 알림 DocumentBuilderSwaggerOptions를 생성하고 새로 생성 된 options에 대해 createDocument()를 실행한 다음 두 번째 SwaggerOptions에 대한 작업을 시작하기 전에 setup()을 사용하여 즉시 "제공"해야 합니다. 두 번째 Swagger 사양의 경우. 이 특정 순서는 Swagger 구성이 다른 옵션으로 대체되지 않도록하기위한 것입니다.

Working with enums

SwaggerModuleEnum을 식별할 수 있으려면, @ApiModelPropertyenum 속성을 값 배열로 수동으로 설정해야 합니다.

@ApiModelProperty({ enum: ['Admin', 'Moderator', 'User']})
role: UserRole;

UserRole 열거형은 다음과 같이 정의할 수 있습니다.

export enum UserRole {
  Admin = 'Admin',
  Moderator = 'Moderator',
  User = 'User',
}

warning Note The above usage can only be applied to a property as part of a model definition.

Enums can be used by itself with the @Query() parameter decorator in combination with the @ApiImplicitQuery() decorator.

@ApiImplicitQuery({ name: 'role', enum: ['Admin', 'Moderator', 'User'] })
async filterByRole(@Query('role') role: UserRole = UserRole.User) {
  // role returns: UserRole.Admin, UserRole.Moderator OR UserRole.User
}

warning 힌트 enumisArray@ApiImplicitQuery()와 함께 사용할 수 있습니다

isArraytrue로 설정하면 enummulti-select로 선택할 수 있습니다.

Working with arrays

속성이 실제로 배열일 때 유형을 수동으로 표시해야 합니다.

@ApiModelProperty({ type: [String] })
readonly names: string[];

위의 그림처럼 배열의 첫 번째 요소로 타입을 입력하거나 isArray 속성을 true로 설정하십시오.

Tags

처음에는 DocumentBuilder를 사용하여 cats 태그를 만들었습니다. 지정된 태그에 컨트롤러를 연결하려면@ApiUseTags(...tags) 데코레이터를 사용해야합니다.

@ApiUseTags('cats')
@Controller('cats')
export class CatsController {}

Responses

커스텀 HTTP 응답을 정의하기 위해 @ApiResponse()데코레이터를 사용합니다.

@Post()
@ApiResponse({ status: 201, description: 'The record has been successfully created.'})
@ApiResponse({ status: 403, description: 'Forbidden.'})
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}

예외 필터 섹션에 정의된 일반적인 HTTP 예외와 마찬가지로 Nest는 핵심 @ApiResponse 데코레이터에서 상속되는 사용 가능한 API 응답 세트를 제공합니다.

  • @ApiOkResponse()

  • @ApiCreatedResponse()

  • @ApiBadRequestResponse()

  • @ApiUnauthorizedResponse()

  • @ApiNotFoundResponse()

  • @ApiForbiddenResponse()

  • @ApiMethodNotAllowedResponse()

  • @ApiNotAcceptableResponse()

  • @ApiRequestTimeoutResponse()

  • @ApiConflictResponse()

  • @ApiGoneResponse()

  • @ApiPayloadTooLargeResponse()

  • @ApiUnsupportedMediaTypeResponse()

  • @ApiUnprocessableEntityResponse()

  • @ApiInternalServerErrorResponse()

  • @ApiNotImplementedResponse()

  • @ApiBadGatewayResponse()

  • @ApiServiceUnavailableResponse()

  • @ApiGatewayTimeoutResponse()

사용 가능한 HTTP 예외 외에도 Nest는 HttpStatus.OK, HttpStatus.CREATEDHttpStatus.METHOD_NOT_ALLOWED에 대한 단축 데코레이터를 제공합니다.

@Post()
@ApiCreatedResponse({ description: 'The record has been successfully created.'})
@ApiForbiddenResponse({ description: 'Forbidden.'})
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}

Authentication

DocumentBuilder 클래스의 addBearerAuth() 메소드를 사용하여 베어러 인증을 활성화할 수 있습니다. 그런 다음 선택한 경로 또는 전체 컨트롤러를 제한하려면 @ApiBearerAuth()데코레이터를 사용하십시오.

@ApiUseTags('cats')
@ApiBearerAuth()
@Controller('cats')
export class CatsController {}

OpenAPI 설명서는 다음과 같습니다.

File upload

@ApiImplicitFile 데코레이터와 @ApiConsumes()를 사용하여 특정 메소드에 대한 파일 업로드를 활성화 할 수 있습니다. 다음은 File Upload 기술을 사용한 전체 예입니다.

@UseInterceptors(FileInterceptor('file'))
@ApiConsumes('multipart/form-data')
@ApiImplicitFile({ name: 'file', required: true, description: 'List of cats' })
uploadFile(@UploadedFile() file) {}

Decorators

사용 가능한 모든 OpenAPI 데코레이터에는 핵심 데코레이터와 명확하게 구분할 수있는 Api접두사가 있습니다. 아래는 정의된 사용 수준 (적용 가능한 경우)을 가진 엑스포트된 데코레이터의 전체 목록입니다.

실제 사례는 여기에서 확인할 수 있습니다.

Last updated