LoginSignup
23
20

More than 5 years have passed since last update.

Golangで学ぶREST-APIの世界 OpenAPI(Swagger)

Last updated at Posted at 2019-04-06

はじめに

Webシステムでよく使われるREST-API、個人的に勉強した際「ドキュメントや実装を整理したいよな~」とか思って自分で頑張ろうとしていました。
しかし世の中には標準というものがあるmので、REST-APIにもOpenAPI(swagger)という記述方法が一般的になっています。
ここではswaggerと、swagger+golang web frameworkを利用出来るツールの紹介をしていきます。

OpenAPI(swagger)とは

ざっくりいうと、「REST-APIの定義に関する記述方法を取り決めたもの」になります。一定の法則に従って記述するため、整形された描画や自動生成が可能となっています。
詳細なSpecについてはOpenAPI Specificationを参照ください。

整形された描画

ファイルの形式はYAMLJSON形式のファイルとなっています。
ファイル自体はテキストベースなんですが、これをswagger-uiのようなツールを使って開くと、綺麗に成形されたドキュメントに早変わりします。

以下図はswagger-uiのサイトから抜粋。/petというURIに対してGET/POST/PUT/DELETEでアクセスするとどうなるか?が見やすく表示されています。めっちゃ便利!

他にはswagger editorというものも非常に便利です。
ローカルインストールもオンラインでの利用も出来るエディタで、ファイルのインポート・エクスポートやJSON⇔YAMLの変換も出来ます。

自動生成

書き方が決まっているので、Swaggerファイルからコードのひな型を出力したり、またはコードからSwaggerファイルを作成したりといったことが可能になります。
「swagger コード生成」等で検索すると沢山情報が出てきます。swagger-codegen等使えそうなものが沢山ありますね。(触っていないので割愛)
Swagger→コード生成はこの辺りの記事が参考になりそうです。
まだAPI定義管理で消耗してるの?〜Swaggerを用いた大規模アプリ時代のAPI定義管理とコードジェネレート〜

ただ、現場に元々いた人の話を聞くと、ドキュメント作成→コード生成だと、最初はいいけど変更が多くなると割と面倒が増えるので、コード→Swaggerファイル作成の方がメンテナンスが楽かもという話。
個人的な経験としても、ドキュメント→コードよりもコード→ドキュメントの自動生成の方が嫌がる人が少ない、ハードルが低い印象があるので、こちらに注目していきたいと考えています。

Golangでのswagger利用例

golangのwebフレームワークgin-gonic/ginの中のissue Automatically generate RESTful API documentation with Swaggerで色々な方法がやり取りされていました。その中で今回はgithub.com/savaki/swagを紹介。

github.com/savaki/swagによる生成

まずは必要なライブラリを取得しましょう。コードのサンプルとして標準とgin-gonic/ginlabstack/echogorilla/muxjulienschmidt/httprouterというWebフレームワークのサンプルが用意されています。

今回はgin-gonic/ginを使ってみます。

$ go get github.com/savaki/swag
$ go get github.com/gin-gonic/gin

使い方はsampleを動かした方がはやいのでコードをcloneします。

$ git clone https://github.com/savaki/swag.git

後はswag/examples/gin/main.goを起動するだけ。ginの場合は設定したAPIの情報が出力されます。

$ cd swag/examples/gin/
$ go run main.go
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] POST   /pet                      --> main.handle (1 handlers)
[GIN-debug] GET    /pet/:petId               --> main.handle (1 handlers)
[GIN-debug] GET    /swagger                  --> github.com/gin-gonic/gin.WrapH.func1 (1 handlers)

ここで気になるのが/swagger。コードとしては以下のような形で、apiというのはURIとmethod等の情報を登録したものになります。
これをやっておくと、/swaggerにアクセスした際にJSON形式のswaggerが取得できるようになります。

main.go
router.GET("/swagger", gin.WrapH(api.Handler(enableCors)))

api情報はこんな感じで各URIに対して必要な情報と、swaggerに吐き出すための情報を記載していく形です。
ただコードを書くよりは情報が増えますが、「コメントで説明する代わりに説明文を登録してる」くらいに考えれば、ドキュメントを書くよりは手間じゃないかな。
他のツールではコメントルールによりファイル出力をするものもありましたが、こちらの方がコードの整理にも繋がるので個人的には好きです。

main.go
        post := endpoint.New("post", "/pet", "Add a new pet to the store",
                endpoint.Handler(handle),
                endpoint.Description("Additional information on adding a pet to the store"),
                endpoint.Body(Pet{}, "Pet object that needs to be added to the store", true),
                endpoint.Response(http.StatusOK, Pet{}, "Successfully added pet"),
        )
        get := endpoint.New("get", "/pet/{petId}", "Find pet by ID",
                endpoint.Handler(handle),
                endpoint.Path("petId", "integer", "ID of pet to return", true),
                endpoint.Response(http.StatusOK, Pet{}, "successful operation"),
        )

        api := swag.New(
                swag.Endpoints(post, get),
        )

        router := gin.New()
        api.Walk(func(path string, endpoint *swagger.Endpoint) {
                h := endpoint.Handler.(func(c *gin.Context))
                path = swag.ColonPath(path)

                router.Handle(endpoint.Method, path, h)
        })

実際に/swaggerにアクセスして取得した情報をswagger editorで表示するとこのような形になります。
JSON形式を自動でYAMLに変換してもらえるのが便利。後はswaggerの書式を細かく覚えなくてもいいので、swaggerの導入としてもよさそうですね。

swagger.png

23
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
20