GrapeとSwaggerだけでAPIを記述していく準備

※ 開発するという意味じゃないです。開発ならサーバ側、クライアント側ともにテストが要るでしょう。あと、「Swaggerに則った仕様の書き方」については完全にスルーです。そこはツール任せ。

日本でも2年前くらいから関連する情報が出回っていてだいぶ出遅れ感があるが、Grape と Swagger を試してみて分かってきたことを吐き出しておく。

Swaggerとは

Swagger – The World's Most Popular Framework for APIs.

Swagger の全容は割と分かりにくい。Swagger を中心にして OpenAPI というものもできているが、こっちの方が分かりやすい。

Home | Open API Initiative

いわく

The OAI is focused on creating, evolving and promoting a vendor neutral API Description Format based on the Swagger Specification.

だそうである。ということはまず何かを記述するフォーマットがあるわけだ。

Specification – Swagger

フォーマットに関してはざっくり言うと「JSON で API の仕様を記述」しようというもの。間違えないでね。「JSON API を構築するものではなく、JSON で API の仕様を記述する」です。ちょっとややこしい。

まぁ仕様です。Spec です。Spec を書く。そのために周辺の便利ツールが揃っているのが Swagger の Swagger たるゆえん。

最初に見るべきはSwagger UIのデモ

Swagger UI

Swagger UI は見てわかる通り「動かせる API ドキュメント」である。これについては自分の中では

Google API Reference と Google APIs Explorer が組み合わさったようなものだなー

という感想が浮かんで腑に落ちた。これを実現するために必要なものが

JSON で記述された仕様

なわけだ。

動かせる仕様の意味

仕様と実装が乖離しない

仕様って仕様だけで独立してるとコードの変更に追随できなくなったりいろいろ悲しい宿命を背負いがちなんだけど、Web API に限れば結局エンドポイントと入力と出力が分かればいいわけだし、これは自然言語のフリーフォーマットで書かなきゃいけないもんじゃないよね。JSON で書いて動かせるようにするってのはなかなか面白い。

特定の実装言語、実装技術に依存せずAPIを記述できる

Swagger の Spec はすでに AWS API Gateway などで利用可能となっている。

自分の理解している範囲内で例えると Selenium Builder で吐き出した仕様を SauceLabs で実行できるようなものだ。これは思いっきり Selenium という特定技術に依存しているんで、まったく同じじゃないんだけど。

なるほど。これは便利だ。

仕様の記述方法の一つとしてのSwagger Editor

Swagger UI を試すとまず思うのは

「これ自分でも作りたい」

だと思う。あれ、思わない? 思ってくれ。思ったとしよう。思ったら次は Swagger Editor だ。

Swagger Editor

左のペインの YAML を書き換えると JSON のドキュメントが自動生成されて右ペインの UI が更新される。なんとなく書き換えているうちはちょっと楽しい。これは

すでに完成された API があってそれの仕様を記述するのには向いている。

あくまで仕様を書いてるので、例えばこの仕様が実現しにくいものだったりしたらどうしようとか、そういう検証や予備実装目的には使えない。

その場合はどうしたらよいか? そう、Ruby 使いなら Grape だ。たぶん。1

grape-swaggerでサクサクAPIを実装

ruby-grape/grape: An opinionated framework for creating REST-like APIs in Ruby.

Grape は

  • API における Sinatra のような DSL を提供してくれる Rack アプリのベースクラス
  • Rack アプリなので直接 Rack::Builder しても Sinatra で use しても Rails で mount してもよい

この Grape に Swagger 用のドキュメントを自動生成する grape-swagger というツールが存在する。

ruby-grape/grape-swagger: Add swagger compliant documentation to your grape API

これを組み合わせる。すると例えば

desc 'dumb endpoint'
get :foo do
  {}
end

add_swagger_documentation  # <- Attention !

こういう Grape の記述から以下のような Swagger 向けの JSON が自動生成される。

"/foo": {
  "get": {
    "summary": "dumb endpoint",
    "description": "dumb endpoint",
    "produces": ["application/json"],
    "responses": {
      "200": {
        "description": "dumb endpoint"
      }
    },
    "tags": ["foo"],
    "operationId": "getFoo"
  }
}

grape-swaggerのJSONのendpoint

何も設定しないと

http://localhost:9292/swagger_doc

に出力される。ただし、このままだと本当にただの JSON であって、何の嬉しみもない。Swagger の嬉しみはやはり Swagger UI で操作可能なところだ。

自分で書いているAPIに対してSwagger UIを用意する方法

生成された JSON を表示、操作するためには何らかの方法で Swagger UI を用意する必要がある。

`npm install swagger-ui` && rack-cors

恐らくこれが最もベーシックな構成。

基本的に Swagger 関係は npm 周りがいちばん充実している。2Swagger UI も `npm install swagger-ui` でインストールできる。この場合、

  • Grape で API を提供している Rack サーバ
  • Swagger UI を提供しているサーバ(あるいは file://

の2つが存在することになる。

Swagger UI は JavaScript で実際に API へ http request を投げるので、API サーバと Swagger UI サーバが別々に存在する場合は API サーバ側に CORS 設定が必要になる。

今回の方法は Grape ( Rack ) で API サーバを立てるので、Rack のレイヤーで CORS を設定する rack-cors を利用して CORS の設定をすることになる。

rack-swagger

Swagger UI を提供する Rack アプリ、rack-swagger がある。

※ これを書いている時点で 0.0.6 だけど2年あまり放置されている

rentpath/rack-swagger: Serve up Swagger UI and docs.

これを使えば同一の Rack サーバ上で

  • Grape による API サーバ
  • Swagger UI

の両方が提供されるので CORS の設定は不要になる。提供する API が JavaScript からのアクセスを想定していないのならこれもアリかも。

ただし rack-swagger はちょっとクセがあって、Swagger のエコシステムで標準的な

/swagger_doc

という endpoint を見にいかない。

/docs/api-docs

を見にいこうとするので、grape-swagger 側で

add_swagger_documentation monut_path: '/docs/api-docs'

としておく。3これの実験をやったリポジトリを作ったので、これを見てもらうと理解が早いと思う。

wtnabe/ruby-grape-swagger-example

  1. ちなみにワタクシここに至るまで Grape を使ったことがなかったので実は Rubyist ではないのかもしれない。 

  2. CodeGen は Java だけど 

  3. rack-swagger の見に行くパスも変更できなくはないと思うんだけど、アレコレ決め打ちの処理が見え隠れしているので、そっちは諦めた方が早いと思う。 

More