🐁

OpenAPI を実装する Go サーバー oapi-codegen と ogen を比較

2024/03/06に公開

はじめに

コードなんて人間が書かなければ書かないほどいいもんです。第二弾です。

第一弾 ↓

https://zenn.dev/otakakot/articles/df3e935ac0e6a8

今回は OpenAPI を活用したサーバー実装におけるコード自動生成ライブラリを触ってみて比較をしたのでメモとして残しておきます。

OpenAPI

https://www.openapis.org/

The OpenAPI Specification provides a formal standard for describing HTTP APIs.

OpenAPI を活用することで HTTP API を定義することができます。

ライブラリ

今回 OpenAPI の定義を解釈してコードを自動生成してくれるツールとして oapi-codegenogen を比較します。

OpenAPI からコードを自動生成するツールとしてスター数がもっとも多い openapi-generator がありますが、多様な言語に対応してくれるフレームワークという感じがあり、また、使い勝手も個人的に好みではなかったので除外しました。(スター数が多いのは多数の言語に対応しているからですかね。)

準備

インストール

oapi-codegen は以下のコマンドにてインストールします。

go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@lates

※ 私は go install でツールをインストールすることが多いです。 Windows だろうが Mac だろうが Linux だろうが同じコマンドでインストールできるので。
ogen はコマンドをインストールせず go generate で実行する形にしています。

バージョン

go version
go version go1.22.0 darwin/arm64
oapi-codegen --version
github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen
v2.1.0
ogen version

v0.82.0
※ 手元にインストールせずに利用するので実行時のバージョンタグを記載

openapi.yaml

コード実装をするサンプルファイルとして下記のリポジトリの yaml を拝借します。

https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore.yaml

検証したい要素を加味して以下のような yaml を新たに定義します。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/openapi.yaml

比較観点

今回の記事においては以下に示す観点に注目します。

  • 特徴
  • コード生成方法
  • 生成されるコード
  • 実装方法
  • ミドルウェアの実装
  • 認証・認可の実装

oapi-codegen

https://github.com/deepmap/oapi-codegen

特徴

  • デフォルトのルーティングエンジンとして echo を採用
  • ほかにも ChiGinGorilla/muxFiber、および Iris も選択可能
  • clienttype のみの生成も可能

コード生成方法

opai-codegen コマンドを利用して以下のように生成します。

oapi-codegen -package <package> opanapi.yaml > xxx.gen.go

生成されるコード

サーバー(echo)実装用 interface 定義などのコードは以下のように生成されます。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/pkg/oapi/server.gen.go

実装方法

おまじない含め以下のように interface を満たす実装をします。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/cmd/oapi/main.go#L119-L198

ミドルウェアの実装

echo に基づき以下のように実装します。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/cmd/oapi/main.go#L34-L36

認証・認可の実装

こちらも echo に基づき以下のように実装します。
ロジックに関しては自前で組む必要があります。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/cmd/oapi/main.go#L38-L86

ogen

https://github.com/ogen-go/ogen

特徴

  • 生成されたコードで refrect や interface{} を使わない
  • 独自のルーティング機構
  • 標準の OpenAPI v3 で完結
  • Optional や Nullable に対応
  • OpenTelemetry に対応
  • 2024/03/06 現在は安定版(v1)は未リリース

私が ogen を知ったきっかけである @p1ass さんの記事もおすすめです。

https://blog.p1ass.com/posts/ogen/

コード生成方法

以下のように generate.go を用意し go generate ./... にて生成します。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/pkg/ogen/generate.go

生成されるコード

複数ファイル生成されます。
サーバー実装用 interface 定義のコードは以下のように生成されます。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/pkg/ogen/oas_server_gen.go

実装方法

おまじない含め以下のように interface を満たす実装をします。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/cmd/ogen/main.go#L72-L171

ミドルウェアの実装

Middleware が戻り値となるように以下のように実装をし

https://github.com/otakakot/sample-go-openapi-gen/blob/main/cmd/ogen/main.go#L195-L208

自動生成コードに含まれるWithMiddleware() を利用して設定します。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/cmd/ogen/main.go#L28-L34

認証・認可の実装

おまじない含め以下のように実装します。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/cmd/ogen/main.go#L173-L193

そしてミドルウェア同様以下のように設定します。

https://github.com/otakakot/sample-go-openapi-gen/blob/main/cmd/ogen/main.go#L28-L34

所感

  • 厳密に実装できそうなのは ogen
  • ミドルウェアの実装を楽にしたいなら oapi-codegen
  • ライブラリ( echogin ) に慣れ親しんでいる方は oapi-codegen

おわりに

個人的には oapi-codegen より ogen の方が OpenAPI 定義に対して厳密に実装ができるのかなと思っています。(特にレスポンス)
oapi-codegen は型の定義はあるもののレスポンスは echo の形式になるので別の型を返すことも可能となります。
ただ、ミドルウェアなどの追加実装に関しては echo が成熟しているので oapi-codegen を活用した方がよさそうです。

今回実装したコードは以下に置いておきます。

https://github.com/otakakot/sample-go-openapi-gen

Discussion