読者です 読者をやめる 読者になる 読者になる

ボクココ

サービス開発を成功させるまでの歩み

Rails における API 開発 (設計とGem選定編)

AWS Rails

ども、@kimihom です。

すっかり年末感漂う感じになってきた。本ブログではそんなこと関係なく、引き続き API の話題。

前回のAPI 開発において認証以外で気をつけるべきこと で API 開発における検討事項を列挙した。その前の API 認証の設計も踏まえて、今回は実際に Ruby on Rails を事例に設計を始めていきたい。

選定した Gem

今回は Rails の API 開発でおなじみの Grape とその周辺 Gem を利用する。そもそも何故 Grape なのかというと、1つ目は REST API の書き方に特化している DSL (domain-specific language) であるため、簡単にAPI が作成できる点がある。実装の例は Grape の Github を閲覧してみていただきたい。2つ目に、APIの開発に特化しているため、余計な Rails の middleware を削ぎ落としてくれているので通常の Rails アプリより高速に動作する点がある。そこで最近の Rails 動向に敏感な方ならご存知の通り、 rails-api という、 API に特化した Rails アプリを作成できる Gem が Rails 5 でマージされて通常で利用できるようになる。ただ rails-api を利用するには API 用の Rails プロジェクトを一から作る必要があった。ということで、既に Rails アプリを持っていて、その中に組み込むことは困難である。とすると、2つの Rails アプリを運用することになるが、これだと Rails の migration 周りが煩雑になりDB管理が難しくなると判断した。 既にある Rails アプリに組み込める Grape が私にとって今回の開発に合っていた。

Grape には Grape 自体に付随する Gem として、 リクエストやレスポンスをモデルと紐付ける grape-entity, Swagger 形式でドキュメントを出力してくれる grape-swagger、その出力した Swagger 形式を 自分のRails アプリのViewとして見ることができるようになる grape-swagger-rails がある。これらを上手く組み合わせれば、より効率的に API の開発とドキュメントの開発を並行で行うことができる。

選定した認証方法

API 認証の設計 を踏まえて、今回のAPIは事前に サービス内であらかじめトークンを発行し、トークンベースで認証を行う API を採用することにした。

認証は devise を利用しているので関連の Gem を探してみると、devise_token_auth や、 simple_token_authentication などがあった。 devise_token_auth を見た限り、これは例えば AngularJS などを使ってバックエンドで Rails という選択をした時などに大変有用なツールであると感じた。しかし、devise_token_auth のトークンを発行するのに、/sign_in にアクセスしないとトークンが取得できないことが発覚。 sign_in するにはパスワード認証をする必要があり、これではトークンベースでの開発ができない。 この点が決定打となり採用は見送った。

simple_token_authentication も同じような設計であった。また Grape 連携となるとそれ専用のブランチが切られていて、そもそも Grape と連携する想定ではあまりなさそうな Gem であるように見受けられた。今後のアップデートなどを考えるとあまり simple_token_authentication と Grape のコンビではやらないほうがいいと感じた。

ということで、自前でトークン認証を実装することにした。最低限のシンプルなトークンで良かったので、Rails + Grape + API Key Authentication を参考に現在の Rails プロジェクトに当て込んでみることにした。この記事に書かれている方法はまさに今回やりたかった方法で、サービス内で一度トークンを発行したら、そのトークンをベースに API にアクセスできるようにするやり方だ。

URL、ディレクトリ 設計

基本的には REST API なのであまり問題にはならないのだけど、 バージョニングの話と Grape を利用する上での構成を検討する必要が出てくる。

まずバージョニングに関してはシンプルに https://ホスト名/v1/resouces という感じでパスの一番最初にバージョンを指定できるようにした。これが誰にとっても一番わかりやすいと感じているためだ。Grape は Rails のコントローラとは離れている存在なので、別のところに Grape プロジェクトを置く必要があるのだけど、今回はシンプルに #{RAILS_ROOT}/app/api/v1/resources.rb という感じで置くようにした。

他の例を見るとhttps://ホスト名/api/v1/resourcesというように、パスにapiを含めるところも多いようだ。だが今回は最後に Amazon API Gateway を通して API アクセスするようにするため、ホスト名の時点でAPIだとわかるようになるので api というパスは含めなかった。

Amazon API Gateway の利用

Amazon API Gateway を利用する理由としては、

  • 最大で数十万の同時 API 呼び出しを受け付け、処理することが可能
  • トラフィック管理
  • アクセス管理
  • モニタリング

などがある。キャッシュの仕組みやリトライの仕組みなどもあるので、今後 API が高負荷になった時に諸々対策できることがある。このように API開発で共通の実装を楽にしてくれる点があったのと、作成した API用の SDK 自動生成や Postman 形式の出力などをサポートしてくれているのも魅力的だった。

そんで今回一番苦労したのだけれども、 aws-apigateway-importer を使えば、Grape プロジェクトで作成した Swagger 形式のドキュメントをそのまま Amazon API Gateway に取り込むことができる。これに関してがっつりやった人はまだ日本ではほとんどいないだろうから、有用な記事を後日書くことができると思っている。

終わりに

今回はこんな感じで Grape, Swagger, Amazon API Gateway 周りを中心にやっていくことにした。

次回以降、本格的にコードを含んだ実装編をお届けしたい。