ローカルで Swagger UI + Sinatra を試してみた

最近よく Swagger の話題を聞くので,少し調べてみた.

Swagger とは

Swagger を一言で表すと「REST API ドキュメントのためのフレームワーク」で,API 定義を JSON or YAML で書くことによって,開発者とコンピュータの双方で "Readable" なドキュメントを生成することができる.また様々な Swagger Tools と組み合わせることで,ドキュメントとしての枠組みを超えて,エコシステムとして活用できる.

  • Swagger Core
  • Swagger Codegen
  • Swagger UI
  • Swagger Editor
  • Integrations
  • Commercial Tools

話としてはよくわかるんだけど,実際どうなんだろうと思って,ローカルで試してみた.

試してみた

今回は Swagger Codegen は使わずに,Swagger Editor で書いた Swagger Specification を Swagger UI にインポートして,Sinatra で実装した API をコールするところまでを試してみた.既にもうツール名が並びすぎて意味不明って思う人もいそう.

Sinatra で簡易的な API を用意する

詳細は Kakakakakku/sinatra-swagger-sample を見てもらうとして,/users のエンドポイントでダミーデータを返すようにした.

get '/users' do
  content_type :json
  [
    { id: 1, name: 'User1' },
    { id: 2, name: 'User2' },
    { id: 3, name: 'User3' },
    { id: 4, name: 'User4' },
    { id: 5, name: 'User5' }
  ].to_json
end

Swagger Editor で Swagger Specification を書く

Swagger Editor をローカルに落としてきて npm 経由で起動すると http://localhost:8080/#/ でアクセスできるようになる.デフォルトで表示される YAML を参考にしながら何となく Swagger Specification を書いてみた.ちなみに Swagger Editor Live Demo もあるので,無理してローカルに用意せずに,ここで書いても良かったかもなーと今さら思ったり.

swagger: '2.0'
info:
  title: Sample API
  description: This is my sample API
  version: 1.0.0
host: localhost:4567
schemes:
  - http
basePath: /
produces:
  - application/json
paths:
  /users:
    get:
      summary: All users
      description: All users
      responses:
        '200':
          description: An array of users
          schema:
            type: array
            items:
              $ref: '#/definitions/User'
definitions:
  User:
    type: object
    properties:
      id:
        type: integer
        description: User id
      name:
        type: string
        description: User name

Swagger Specification をダウンロードする

形式は JSONYAML を選択できる.

f:id:kakku22:20151129011719p:plain

Swagger UI を使う前に

Swagger UI に Swagger Specification を指定するときに,ローカルで file://プロトコルが許容されてなく動かなかった.

Can't read swagger JSON from file://...

今回はワークアラウンド的な対応として Sinatra/resources のエンドポイントを叩くと Swagger Editor でダウンロードした JSON を返すように実装した.

get '/resources' do
  content_type :json
  swagger_json = File.open('./docs/swagger.json')
  swagger_json
end

さらにローカルで実行している Swagger UI と Sinatra 間で CORS の問題が発生してしまうため,britg/sinatra-cross_origin · GitHub を使って対応した.

require 'sinatra/cross_origin'

configure do
  enable :cross_origin
end

ローカル環境に関しては似たような Issue が上がっていた.

Swagger UI で Swagger Specification を読み込む

Swagger UI に http://localhost:4567/resouces を指定して正しく読み込まれていることを確認できたし,/users のエンドポイントもコールできた.ドキュメントから API をコールできるのは普通に良いなーという印象だった.

f:id:kakku22:20151129013143p:plain

まとめ

ここまで試してみたものの,まだあまりよくわかってないし,Swagger Specification を書くのがあまりに面倒だなーと思ったりした.まぁ今回は Swagger Specification を直接書いてしまったけど,これだと確実にメンテナンスが形骸化するので,Swagger Codegen を使ってコード上のアノテーションから自動生成するような仕組みにすれば良いんだろうけど,とは言え,アノテーションを書くとしても結構書くこと多いんじゃないかと思う.引き続き調べる!