🐁

go:embed を使って OpenAPI を公開する

2024/02/18に公開

はじめに

OpenAPI を使って開発するとき Swagger UI は重宝します。

https://github.com/swagger-api/swagger-ui

以前これをサーバーから返せるようにしたことがありましたが、めんどくさくなって挫折しました。

https://github.com/swagger-api/swagger-ui

petstore サイトにアクセスするときにクエリパラメータを付与すると任意の openapi.yaml に対して閲覧できることを知りました。

じゃあ、定義した openapi.yaml を Go サーバーから返せるようにして petstore でアクセスできるようにすればいいのでは?ということで実装してみたという記事になります。

※ Go のバージョンは 1.22.0 です。

go:embed

Go の embed というパッケージを利用するとファイルをバイナリに埋め込むことができます。

https://pkg.go.dev/embed

さっと知りたい方は、下記の記事が参考になります。

https://future-architect.github.io/articles/20210208/

petstore

petstore は Swagger UI が確認できるサイトです。

https://petstore3.swagger.io/

実装

go:embed で openapi.yaml を埋め込みます。

//go:embed openapi.yaml
var yaml embed.FS

※ main.go と openapi.yaml はルートディレクトリに配置しています。

openapi.yaml にアクセスできるようにハンドラーを設定します。

mux.Handle("GET /", cors(http.FileServer(http.FS(yaml))))

cors を設定しないとアクセスできなかったので以下の関数で設定しています。

func cors(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
		h.ServeHTTP(w, r)
	})
}

/petstore へのアクセスでクエリパラメータを付与して https://petstore3.swagger.io/ へリダイレクトさせます。

mux.HandleFunc("GET /petstore", func(w http.ResponseWriter, r *http.Request) {
    yaml := "http://localhost:3000/openapi.yaml"

    petstore := "https://petstore3.swagger.io/?url=" + yaml

    http.Redirect(w, r, petstore, http.StatusFound)
})

※ openapi および petstore を管理するサーバーは 3000 でポートを開けています。

アクセス

サーバーを起動し GET /petstore にアクセスすることで以下の画面に遷移します。

こんな感じに打鍵テストもできます。

おわりに

ローカル環境での実装前提です。クラウド環境などにデプロイする際はまた別の考慮が必要です。
また、本番環境に含まれないように調整も必要です。

というか普通に os.Open で yaml ファイル読み込めば良かったじゃん!!!

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

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

Discussion