フラミナル

考え方や調べたことを書き殴ります。IT技術系記事多め

【新規ツール探し】OpenAPI と Swagger に入門してみる

  • 記事作成日:2022/12/03

情報

名前 URL
Github https://github.com/OAI/OpenAPI-Specification
公式サイト https://www.openapis.org/
デモサイト https://editor.swagger.io/
開発母体 OpenAPI Initiative
version 3.1.0
言語 JavaScript
価格 無料
ライセンス Apache-2.0 license

何ができるもの?

  • OpenAPI: 仕様
  • Swagger: 仕様を実装するためのツール

What is OpenAPI? Swagger vs. OpenAPI | Swagger Blog

使い方

このチュートリアルを SwaggerHub を使ってやってみる - https://support.smartbear.com/swaggerhub/docs/tutorials/openapi-3-tutorial.html

openapi: 3.0.0
info:
  version: '1.0.0'
  title: Simple Artist API
  description: A Simple API to illustrate OpenAPI concepts

servers:
  - url: https://example.io/v1

components: {}
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
security: 
  - BasicAuth: []
  
# ----

paths: 
  /artists:
    get:
      description: Returns a list of artists
      parameters: 
        - name: limit
          in: query
          description: Limits the number of items on a page
          schema:
            type: integer
        - name: offset
          in: query
          description: Specifies the page number of the artists to be displyaed
          schema:
            type: integer
      responses:
        '200':
          description: Successfully returned a list of artists
          content:
            appilication/json:
              schema:
                type: array
                items:
                  type: object
                  required: 
                    - username
                  properties:
                    artist_name:
                      type: string
                    artist_genre:
                      type: string
                    albums_recorded:
                      type: integer
                    username:
                      type: string
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
    post:
      description: Lets a user post a new artist
      requestBody:
        required: true
        content: 
          application/json:
            schema:
              type: object
              required: 
                - username
              properties:
                artist_name:
                  type: string
                artist_genre:
                  type: string
                artist_recorded:
                  type: integer
                username:
                  type: string
      responses:
        '200':
          description: Successfully created a new artist
          
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
  
  /artists/{username}:        
    get:
      description: Obtain information about an artist from his or her unique username
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
          
      responses:
        '200':
          description: Successfully returned an artist
          content:
            application/json:
              schema:
                type: object
                properties:
                  artist_name:
                    type: string
                  artist_genre:
                    type: string
                  albums_recorded:
                    type: integer
                
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object 
                properties:           
                  message:
                    type: string

コンポーネントごとにまとめられるので一部リファクタ。

openapi: 3.0.0
info:
  version: '1.0.0'
  title: Simple Artist API
  description: A Simple API to illustrate OpenAPI concepts

servers:
  - url: https://example.io/v1

components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
  
  schemas:
    Artist:
      type: object
      required: 
        - username
      properties:
        artist_name:
          type: string
        artist_genre:
          type: string
        albums_recorded:
          type: integer
        username:
          type: string

  parameters:
    PageLimit:
      name: limit
      in: query
      description: Limits the number of items on a page
      schema:
        type: integer
      
    PageOffset:
      name: offset
      in: query
      description: Specifies the page number of the artists to be displayed
      schema:
        type: integer

  responses:
    400Error:
      description: Invalid request
      content:
        application/json:
          schema:
            type: object 
            properties:
              message:
                type: string
security: 
  - BasicAuth: []
  
# ----

paths: 
  /artists:
    get:
      description: Returns a list of artists
      parameters: 
        - $ref: '#/components/parameters/PageLimit'
        - $ref: '#/components/parameters/PageOffset'
      responses:
        '200':
          description: Successfully returned a list of artists
          content:
            appilication/json:
              schema:
                items:
                  $ref: '#/components/schemas/Artist'
        '400':
          $ref: '#/components/responses/400Error'
    post:
      description: Lets a user post a new artist
      requestBody:
        required: true
        content: 
          application/json:
            schema:
              $ref: '#/components/schemas/Artist'
      responses:
        '200':
          description: Successfully created a new artist
          
        '400':
          $ref: '#/components/responses/400Error'
  
  /artists/{username}:        
    get:
      description: Obtain information about an artist from his or her unique username
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
          
      responses:
        '200':
          description: Successfully returned an artist
          content:
            application/json:
              schema:
                type: object
                properties:
                  artist_name:
                    type: string
                  artist_genre:
                    type: string
                  albums_recorded:
                    type: integer
                
        '400':
          $ref: '#/components/responses/400Error'

利用シーン

API スキーマを作成し、モバイル ⇄ バックエンド、フロント ⇄ バックエンド などで通信プロトコルを整備する時に使える。 またこのスキーマからコードを自動生成もできる

❯ docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate -i /local/api.yaml -g go -o /local
[main] INFO  o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO  o.o.c.ignore.CodegenIgnoreProcessor - No .openapi-generator-ignore file found.
[main] INFO  o.o.codegen.DefaultGenerator - OpenAPI Generator: go (client)
[main] INFO  o.o.codegen.DefaultGenerator - Generator 'go' is considered stable.
[main] INFO  o.o.c.languages.AbstractGoCodegen - Environment variable GO_POST_PROCESS_FILE not defined so Go code may not be properly formatted. To define it, try `export GO_POST_PROCESS_FILE="/usr/local/bin/gofmt -w"` (Linux/Mac)
[main] INFO  o.o.c.languages.AbstractGoCodegen - NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).
[main] INFO  o.o.codegen.InlineModelResolver - Inline schema created as _artists_get_400_response. To have complete control of the model name, set the `title` field or use the inlineSchemaNameMapping option (--inline-schema-name-mappings in CLI).
[main] INFO  o.o.codegen.InlineModelResolver - Inline schema created as _artists__username__get_200_response. To have complete control of the model name, set the `title` field or use the inlineSchemaNameMapping option (--inline-schema-name-mappings in CLI).
[main] INFO  o.o.codegen.TemplateManager - writing file /local/model_artist.go
[main] INFO  o.o.codegen.TemplateManager - writing file /local/docs/Artist.md
[main] INFO  o.o.codegen.TemplateManager - writing file /local/model__artists_get_400_response.go
[main] INFO  o.o.codegen.TemplateManager - writing file /local/docs/ArtistsGet400Response.md
[main] INFO  o.o.codegen.TemplateManager - writing file /local/model__artists__username__get_200_response.go
[main] INFO  o.o.codegen.TemplateManager - writing file /local/docs/ArtistsUsernameGet200Response.md
[main] WARN  o.o.codegen.DefaultCodegen - Empty operationId found for path: get /artists. Renamed to auto-generated operationId: artistsGet
[main] WARN  o.o.codegen.DefaultCodegen - Empty operationId found for path: post /artists. Renamed to auto-generated operationId: artistsPost
[main] WARN  o.o.codegen.DefaultCodegen - Empty operationId found for path: get /artists/{username}. Renamed to auto-generated operationId: artistsUsernameGet
[main] INFO  o.o.codegen.TemplateManager - writing file /local/api_default.go
[main] INFO  o.o.codegen.TemplateManager - writing file /local/test/api_default_test.go
[main] INFO  o.o.codegen.TemplateManager - writing file /local/docs/DefaultApi.md
[main] INFO  o.o.codegen.TemplateManager - writing file /local/api/openapi.yaml
[main] INFO  o.o.codegen.TemplateManager - writing file /local/README.md
[main] INFO  o.o.codegen.TemplateManager - writing file /local/git_push.sh
[main] INFO  o.o.codegen.TemplateManager - writing file /local/.gitignore
[main] INFO  o.o.codegen.TemplateManager - writing file /local/configuration.go
[main] INFO  o.o.codegen.TemplateManager - writing file /local/client.go
[main] INFO  o.o.codegen.TemplateManager - writing file /local/response.go
[main] INFO  o.o.codegen.TemplateManager - writing file /local/go.mod
[main] INFO  o.o.codegen.TemplateManager - writing file /local/go.sum
[main] INFO  o.o.codegen.TemplateManager - writing file /local/.travis.yml
[main] INFO  o.o.codegen.TemplateManager - writing file /local/utils.go
[main] INFO  o.o.codegen.TemplateManager - writing file /local/.openapi-generator-ignore
[main] INFO  o.o.codegen.TemplateManager - writing file /local/.openapi-generator/VERSION
[main] INFO  o.o.codegen.TemplateManager - writing file /local/.openapi-generator/FILES
################################################################################
# Thanks for using OpenAPI Generator.                                          #
# Please consider donation to help us maintain this project 🙏                 #
# https://opencollective.com/openapi_generator/donate                          #
################################################################################

❯ ls
README.md                                     go.mod
api                                           go.sum
api.yaml                                      model__artists__username__get_200_response.go
api_default.go                                model__artists_get_400_response.go
client.go                                     model_artist.go
configuration.go                              response.go
docs                                          test
git_push.sh                                   utils.go

API に対応した model やクライアントコードが自動生成されるので、これを組み込めばすぐに使える。

Stoplight Studio を使うと GUI で簡単に Open API Schema を生成できるとのことなので、こういうツールで楽するのが良いだろう。

登場背景

by DeepL

OASは、REST APIのためのプログラミング言語にとらわれない標準的なインターフェース記述を定義しており、ソースコードへのアクセス、追加のドキュメント、ネットワークトラフィックの検査を必要とせずに、人間とコンピューターの両方がサービスの能力を発見し理解できるようにします。OASによって適切に定義された場合、コンシューマは最小限の実装ロジックでリモートサービスを理解し、対話することができる。インターフェイス記述が低レベルのプログラミングのために行ってきたことと同様に、OASはサービスを呼び出す際の当て推量を排除します。

OpenAPI Initiative (OAI) は、API の記述方法を標準化することに大きな価値を見出す、先進的な業界専門家のコンソーシアムによって設立されました。Linux Foundationの下にあるオープンなガバナンス機構として、OAIはベンダーニュートラルな記述形式の作成、進化、普及に注力しています。OpenAPI仕様は、2015年にSmartBear Software社から寄贈されたSwagger 2.0仕様のリブランディングをベースとしています。

https://www.openapis.org/faq

気にすること

  • コード量が多くなってくるとチーム開発がしづらいとのこと
  • 逆に、サーバサイドのコードから OpenAPI を生成するという流れもある
  • デファクトとして使われているツールなのでエコシステムは充実している
  • (個人的な所感として) REST API は gRPC よりも書く量が多い