OpenAPIとは
RESTfulなWebサービスを記述、生成、利用、可視化するためのインターフェースファイルの仕様です。
以前はSwaggerフレームワークの一部でしたが、2016年にOpenAPI Initiativeが統括する独立プロジェクトとなりました。
Swaggerや他のいくつかのツールは、インターフェースファイルを指定してコード、ドキュメント、テストケースを生成することが可能です。
OpenAPIの正確な仕様については、↓から確認できます。
https://swagger.io/specification/
プロジェクトでの利用法
プレセナの一部プロジェクトでは、API定義をOpenAPI仕様に従って記述するだけでなく、定義ファイル(openapi.yaml)からコードを自動生成して利用しています。
OpenAPI定義ファイルの分割
肥大化するopenapi.yaml
当初はAPI定義ファイルであるopenapi.yamlの1ファイルに全ての記述をしていました。
結果として、下記のような問題が発生しました。
これらの問題に対処するためにopenapi.yamlの分割をおこなうことにしました。
openapi.yamlファイルの構成
openapi.yamlのファイルは大きく分けると下の様なブロックに分かれています。
バージョン情報といったメタ情報:info、serversなど
エンドポイントのURLやリクエスト/レスポンス情報:paths
再利用可能なオブジェクト情報:components
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
'200':
description: A paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
・・・略・・・
components:
schemas:
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
・・・略・・・
主に記述量が肥大化してしまうのは pathsとcomponentsであったため、これらを別ファイルに分割しました。
ファイルの分割
ファイルの分割は簡単です。
定義内の他コンポーネントを参照できるようにするフィールドである$ref
を相対パスで記述するだけです。
openapi.yaml
...(infoやserversは省略)...
paths:
/pet:
$ref: "./paths/pet.yaml"
/pet/{petId}/upload-image:
$ref: "./paths/upload-image.yaml"
/paths/pet.yaml
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
required: false
schema:
type: integer
format: int32
responses:
'200':
content:
application/json:
schema:
$ref: "../schemas/Pet" # $refの記述
default:
description: unexpected error
content:
application/json:
schema:
$ref: "../schemas/Error" # $refの記述
/schemas/Pet.yaml
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
フォルダ構造
openapi.yamlをルートファイルとして、同階層にpathとschemasのフォルダを作成しました。
.
├── openapi.yaml
├── paths # pathの定義ファイルを置く
│ ├── pet.yaml
│ ├── pet_find-by-status.yaml
│ ├── ...
│ └── pet_petId_upload-image.yaml
└── schemas # schemasの定義ファイルを置く
├── Pet.yaml
├── User.yaml
├── ...
└── Tag.yaml
paths配下のファイルの命名規則としては、シンプルにエンドポイントURLの「/」を「_」にするファイル名としました。
/paths/pet/find-by-status.yaml
のように階層を深くするアイデアもあったのですが、schemasへの参照を$ref
で記述する際、"../../schemas/Foo"
, "../../../schemas/Bar"
のように 「..」を書く回数の混乱が生じないように現在のような命名規則をとりました。
エンドポイントURLにidが含まれる場合(ex. /pet/{petId}/upload-image)、理想的にはpet_[petId]_upload-image.yaml
のようにしたかったのですが、「[]」を含むと自動生成コードで問題が生じたため、シンプルにpet_petId_upload-image.yaml
としました。
まとめ
分割によって見通しがよく開発をすすめることができるようになりました。
Visual Studio Codeで開発しているなら、この拡張をいれることで$ref
の記述からファイル参照もできるのでおすすめです。
https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi
しばらくこれで開発を進めてみて、課題感がまた出てきたらブラッシュアップしていきたいと思います。