🦁

OpenAPI 3.1.0+Redoc+DockerでAPIドキュメントを分割して管理する(Laravel)

2022/12/09に公開

はじめに

Laravelプロジェクト内でAPIが多くなり、APIドキュメントが肥大化して管理しにくいということで、以下のことを行ったので、共有します。

  • OpenAPIのドキュメントを分割する
  • 自動でファイルを検知し結合する(Docker化)
  • ドキュメントの表示でRedocを導入(Docker化)

OpenAPIのドキュメントを分割する

ファイル構成

<storage/docs>
├─index.yaml //マージ元となるファイル
├─paths
│   ├─user
│   │     ├─login.yaml
│   └─ index.yaml //ルーティングの情報を書く
│      
└─components
       ├─parameters      //リクエストパラメーター用
       │      ├─auth
       │      │    ├─index.yaml  
       │      │    └─login.yaml 
       │      └─index.yaml //authなどフォルダー名を登録する用
       │
       ├─responses      //レスポンス用
       │      └─parameters同様
       └─requestBodies  //リクエストボディー用
              └─parameters同様 

分割のやり方

OpenAPI3.1.0からpathsで$refを使った書き方ができます。
$refを使い、各フォルダーのindex.yamlに登録したcomponentsを参照しにいきます。

index.yaml
openapi: "3.1.0"
info:
  title: APIドキュメント
  version: 1.0.0
  description: APIドキュメント
servers:
  - url: http://localhost:8080
paths:
  $ref: "./paths/index.yaml"
components:
  requestBodies:
    $ref: "./components/requestBodies/index.yaml"
  parameters:
    $ref: "./components/parameters/index.yaml"
  responses:
    $ref: "./components/responses/index.yaml"
tags:
  - name: ユーザー

path/index.yaml
/user/login:
  $ref: "./user/login.yaml"
path/login.yaml
post:
  summary: ユーザーログイン
  responses:
    '200':
      $ref: '#/components/responses/auth/operationsLogin'
    '422':
      $ref: '#/components/responses/common/loginError'
  requestBody:
    $ref: '#/components/requestBodies/auth/userLogin'

ファイルの結合と自動化とDocker化

ファイルの結合

yamlファイルの結合は、swagger-mergerというnpmのライブラリを使用します。
出力時には以前までのファイルを完全に上書きします。

swagger-mergerでのファイル結合のやり方

$ swagger-merger -i index.yaml -o swagger.yaml

説明
-iで分割したファイルの親ファイル(今回で言うindex.yaml)
-oで出力先とファイル名の設定をする

ファイルの結合の自動化

ファイルの変更を検知し、検知したらファイルを結合するようにします。
ファイルの変更の検知はgazeというnpmのライブラリを使用します。

以下のスクリプトでは、./storage/docs/のファイル内で変更を検知したら、yamlファイルを結合するようになっています。

swagger-merge.js
const gaze = require("gaze"); // 先程のライブラリ
const path = require("path");
const merger = require("swagger-merger");

//ファイルを検知するフォルダを指定
const resolve_path = (dir) => path.join("./storage/docs/", dir);

gaze(
    ["index.yml", "paths/**/*", "components/**/*"],//検知するファイルを指定
    { cwd: resolve_path("") },
    (_, watcher) => {
        watcher.on("all", () => {
            merger({
                input: resolve_path("index.yml"),
                output: "./storage/api-docs/api-docs.yaml",//ファイルの出力先
            })
                .then(() => console.log("merge!")) // マージしたときに叫びます
                .catch((err) => console.error(err));
        });
    }
);

ファイル結合のDocker化

今までのファイル検知とファイル結合をDocker化して別コンテナとして管理します。

<storage/docs>
├─docker
│   ├─swagger
│         ├─Dockerfile
│
├─docker-compose.yml
│      
└─project  
       └─swagger-merge.js //先ほどのファイル変更を検知して自動で結合するスクリプト   
              
Dockerfile
FROM node:16-slim

WORKDIR /usr/src/app

RUN npm install --location=global gaze swagger-merger
ENV NODE_PATH "/usr/local/lib/node_modules"
CMD node swagger-merge.js

docker-compose.yml
version: '3'

//省略

swagger:
    build: ./docker/swagger
    volumes:
      - ./project:/usr/src/app
    tty: true

ドキュメントの表示

Redocの導入

swaggerはOpenAPI3.1.0に対応していなく、UIも良いため、Redocを使用しました。
Redocでは、OpenAPIで書かれたyamlファイルをHTMLファイルに変換してドキュメントとして読める状態にしてくれます。
導入は簡単で、redoc-cliをインストールして、コマンドを叩くだけです。

# cliをインストール
$ npm i -g redoc-cli

# swagger.yamlをもとに、/publicにapi-docs.htmlとしてHTMLを作成する
$ redoc-cli bundle swagger.yaml -o /public/api-docs.html

RedocのDocker化

以下のサンプルでは、/var/app/storage/api-docs/api-docs.yamlのファイルを監視して、
変更があれば、/var/app/public/api-docs.htmlにHTMLを書き出すようになています。

Dockerfile
FROM node:18.3.0-slim
RUN npm install --location=global redoc-cli watch-cli

CMD ["redoc-cli"]
docker-compose.yml
version: '3'

//省略

redoc:
    build: ./docker/redoc
    tty: true
    command: >
      watch -p /var/app/storage/api-docs/api-docs.yaml -c "redoc-cli build /var/app/storage/api-docs/api-docs.yaml -o /var/app/public/api-docs.html"
    volumes:
      - ./project/:/var/app

終わりに

ファイルの自動結合のDocker化の時に、tty: trueにして、永続化しないとダメなことに気づくまでかなり時間がかかりました、、

ドキュメントを書くときに、Stoplight StudioやSwagger Editorを使用できなくなることが唯一の欠点です。(OpenAPI3.0.0の場合、使用できます)
ので、SwaggerがOpenAPI3.1.0に対応して欲しいです。

指摘点などありましたら、コメントいただけると幸いです。

Discussion