OpenAPI ドキュメントを分割し、管理を楽にする
🎄この記事はNAVITIME JAPAN Advent Calendar 2023の14日目の記事です。
こんにちは、革靴です。
ナビタイムジャパンで、電鉄・バス事業者向けサービスの開発・運用を担当しています。
はじめに
REST API を開発する際、OpenAPI Specification(以後 OAS と略)の OpenAPI ドキュメントで仕様を定義することが多いと思います。
私はこれまで、OpenAPI ドキュメントは 1 ファイルに全 API の仕様を定義していましたが、API の数や仕様が増えてくると、OpenAPI ドキュメントのファイルサイズが増加し、以下の問題が発生しました。
編集すべき対象箇所を見つけることに時間がかかる
複数人で開発する際、競合が頻発する
これらの問題に対処するために、OpenAPI ドキュメントを分割し、管理するようにしました。今回は、その方法をご紹介します。
OpenAPI ドキュメントの分割方法
OAS のリポジトリに例として上げられている petstore.yaml を使って、ご説明します。
分割後のディレクトリ構成
OpenAPI ドキュメント分割後のディレクトリ構成は、以下のように設計しました。
.
├── parameters # リクエストパラメーター
│ ├── limit.yaml
│ └── petId.yaml
├── pathItems # 各 API のエンドポイント
│ ├── pets.yaml
│ └── pets_petId.yaml
├── schemas # レスポンスボディのスキーマ
│ ├── Error.yaml
│ ├── Pet.yaml
│ └── Pets.yaml
└── root.yaml # 全体の定義
ディレクトリ名は、OAS のコンポーネントオブジェクトのフィールド名で作成し、1 ファイルの単位は、各コンポーネントオブジェクト単位で記述しました。
分割した各 OpenAPI ドキュメントの中身
root.yaml は OAS のルート定義のみを記述しています。
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
$ref: ./pathItems/pets.yaml
/pets/{petId}:
$ref: ./pathItems/pets_petId.yaml
./paths/pets.yaml はエンドポイント /pets の仕様を記述しています。
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- $ref: ../parameters/Limit.yaml
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: ../schemas/Pets.yaml
default:
description: unexpected error
content:
application/json:
schema:
$ref: ../schemas/Error.yaml
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
"201":
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: ../schemas/Error.yaml
./paths/pets_petId.yaml はエンドポイント /pets/{petId} の仕様を記述しています。
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- $ref: ../parameters/PetId.yaml
responses:
"200":
description: Expected response to a valid request
content:
application/json:
schema:
$ref: ../schemas/Pet.yaml
default:
description: unexpected error
content:
application/json:
schema:
$ref: ../schemas/Error.yaml
./parameters/limit.yaml はエンドポイント /pets で利用するクエリパラメーター limit です。
name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
maximum: 100
format: int32
./parameters/petId.yaml はエンドポイント /pets/{petId} で利用するパスパラメーターです。
name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
./schemas/Error.yaml は全エンドポイントで共通したエラー時のレスポンスボディのスキーマです。
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
./schemas/Pet.yaml はエンドポイント /pets/{petId} の正常時におけるレスポンスボディのスキーマです。
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
./schemas/Pets.yaml はエンドポイント /pets の正常時におけるレスポンスボディのスキーマで、配列の要素は ./schemas/Pet.yaml と同じスキーマなので、以下の記述だけで済みます。
type: array
maxItems: 100
items:
$ref: ./Pet.yaml
分割した各 OpenAPI ドキュメントの中で、$ref というキーワードが登場していますが、こちらは別ファイルになった OpenAPI ドキュメントを参照することができ、相対パスで記述することで認識してくれます。
ファイル分割したことで、1 ファイルあたりのサイズは小さくなりました。
petstore.yaml は 113 行なので、1 ファイルでも、それほど問題は発生しにくいと思いますが、これが数千〜数万行のファイルになってくると、話は変わってきます。
分割した OpenAPI ドキュメントの統合
OpenAPI Specification には、様々な周辺ツールが存在します。
OpenAPI ドキュメントから、コードを生成することについて、こちらの記事でご紹介しているので、良ければご覧ください。
これらのツールを利用する際、OpenAPI ドキュメントを分割したことによる不都合が生じます。
例えば「OpenAPIでコードを生成してスキーマ駆動で開発する:GoとTypeScriptの場合」の記事でご紹介している oapi-codegen はインプットに指定する OpenAPI ドキュメントが 1 ファイルでなければなりません。
皮肉なことに、管理しやすくするために分割した OpenAPI ドキュメントは、周辺ツールを利用する場面では、1 ファイルに統合する必要性が出てくるのです。
分割した OpenAPI ドキュメントを 1 ファイルに統合するために、今回は Redocly CLI というツールを使います。
Redocly CLI
複数の OpenAPI ドキュメントを 1 ファイルに統合するだけなら、Redocly CLI 以外にも、以下のツールが存在します。
しかし、Redocly CLI は統合機能以外にも、様々な機能を兼ね備えている点が魅力的です。いくつか例を上げると、以下になります。
OpenAPI ドキュメントから、HTML 形式のドキュメント生成(Redoc)
OpenAPI ドキュメントの静的解析
インストール方法はいくつかありますが、npm を使うと、以下コマンドになります。
$ npm i -g @redocly/cli@latest
bundle コマンドを使い、先ほど分割した OpenAPI ドキュメントを統合した openapi.yaml を出力できます。
$ redocly bundle root.yaml --output openapi.yaml
Redocly CLI のその他の機能
せっかくなので、先ほど言及した統合以外の機能についても、ご紹介します。
build-doc コマンドを使うと、HTML 形式のドキュメントである Redoc を生成できます。デフォルトでは redoc-static.html というファイル名で出力されます。
$ redocly build-docs root.yaml
lint コマンドを使うと、OpenAPI ドキュメントの静的解析ができます。
$ redocly lint root.yaml
静的解析でよく存在する ignore ルール設定も可能なので、気になる場合は、公式ドキュメントをご覧ください。
まとめ
REST API の開発でよく使われる OpenAPI ドキュメントを分割し、管理しやすくする方法と、分割した OpenAPI ドキュメントを Redocly CLI を使って、統合する方法をご紹介しました。
OpenAPI ドキュメントを各 OAS のコンポーネントオブジェクトで分類し、ファイルサイズを小さくしたことで、API の仕様を特定しやすくなり、競合が発生するリスクも下げることができました。
良ければお試しいただき、REST API の開発・運用が楽になれば幸いです。