🥖

FastAPIの開発中にリアルタイムでOpenAPIドキュメントをファイル出力する仕組みを作ってみた

に公開

やりたいこと

FastAPIからOpenAPIドキュメントを出力する処理を自動化したい。

やったこと

開発時にAPIを起動時した際、OpenAPIドキュメントを自動でファイル出力し、かつ、コードの変更があった時にホットリロードでOpenAPIドキュメントを再生成するようにしました。

サンプルコードをGitHubに置いておきました。
https://github.com/k-ibaraki/auto-gen-openapi-in-fastapi

元々は実プロジェクトでやったやつでして、そのままでは公開できないので、公開用シンプル版としてClaude Codeにリライトさせたものになります。便利な時代になった。

FastAPIのOpenAPIドキュメント生成について

世の中には2種類の派閥があります。

  1. API仕様書を基にコードを自動生成する
  2. コードを基にAPI仕様書を自動生成する

FastAPIはOpenAPIドキュメントを自動生成してくれる機能がデフォルトであるので、2の流派の人間に重宝されています。
アプリを起動して、ブラウザから(APIのroot)/docsを開くだけで、OpenAPIドキュメントを確認することができます。

この時点で非常に便利ですが、この機能はあくまでブラウザ上で見ることができるだけなので、設計書のファイルとして他人に渡すときは、ひと手間必要です。
と言っても、非常に簡単で、以下のようなコードを実行するだけです。

with open("openapi.json", "w") as f:
    api_spec = app.openapi()
    f.write(json.dumps(api_spec))

ですが、手動では普通に実行するのを忘れます。
ということで、実行漏れを防ぎ開発効率化をしたいと考えました。

OpenAPIドキュメント出力の方式を考える

では、自動化を考えてみましょう。例えばこんな案もあると思います。

  1. GitHub Actionsでプルリク時に自動生成する
  2. pre-commitで自動生成させる

1の案は、GitHub Actionsから自動で設計書をcommitするのは個人的に怖いので避けました。
2の案は、commitが遅くなるのがストレスなのとその気になれば簡単に動作を止められるので避けました。

ということで3番目の案として、

  1. 開発中のAPI起動中にコードの変更を監視して、ホットリロードでOpenAPIドキュメントをリアルタイム生成する。

という方式をとりました。
まぁ、これも全然完璧じゃなくて、特にわざわざAPIを起動しないと生成されないというのはイマイチかなと思います。でもまぁ開発したあと動作確認しない奴なんていないだろうという判断です。

中身の簡単な解説

実際の中身は最初に貼ったサンプルの通りなので、細かい作り方は書きません。
サンプルの使い方は、Readmeに書いてある(Claudeが書いてくれた)のでそちらを参照してください。

https://github.com/k-ibaraki/auto-gen-openapi-in-fastapi

簡単にポイントだけ解説します。

コードの変更監視

ホットリロードの為のコードの変更監視にはwatchfilesというライブラリを使っています。
https://github.com/samuelcolvin/watchfiles

やりたいことそのままですが、ファイルの変更を検知するライブラリですね。
uv add watchfiles でインストールできます。
このライブラリを使って、以下のようにファイル監視クラスを作っています。

https://github.com/k-ibaraki/auto-gen-openapi-in-fastapi/blob/main/src/file_watcher.py

FastAPIのLifespan Events

今回の処理はAPI起動中に動くものなので、FastAPIと連動して動作する必要があります。そのために使ったのが、Lifespan EventsというFastAPIの機能です。
https://fastapi.tiangolo.com/advanced/events/

次のように書くことで、FastAPIの起動前と終了後に実行する処理を定義することができます。

@asynccontextmanager
async def lifespan(app: FastAPI):
    # アプリ起動前の処理
    print("サーバー起動前の準備")
    
    yield  # ← この間がアプリの稼働期間
    
    # アプリ終了後の処理  
    print("サーバー終了後のクリーンアップ")

app = FastAPI(
    ... # その他の引数
    lifespan=lifespan,  # ライフサイクル管理を設定
)

yieldがポイントで、これを挟んで起動前と起動後の処理の両方をひとつの関数内に書くことができます。
この機能を使って、FastAPI起動前にファイル監視を開始して、FastAPI終了後にファイル監視を停止させています。

https://github.com/k-ibaraki/auto-gen-openapi-in-fastapi/blob/main/src/main.py#L12-L40

実際に動かしてみる

こんな感じです。APIのエンドポイントを増やしてコードを保存すると、ドキュメントも更新されるのが分かるかと思います。

ところで、Zennに動画を貼るのってどうするのがいいのでしょうか? YouTube? gifはツラい。

まとめ

ということで、開発中のコードの変更を検知して自動でOpenAPIドキュメント出力をする機能を作ってみました。たぶんそれなりに便利なんじゃないかなと思っています。

NCDCエンジニアブログ

Discussion