REST API 設計書
Overview
REST APIでの設計についてまとめているセクション。
基本的には「Web API The Good Parts」を参考にしている。
いい設計の考え方
- ユースケースを考えるべき。そうすると目的がはっきりする。
- APIはデータベースのインターフェースではない。そのためのユースケースになる。
データベースのテーブルに紐付ける1対1のAPIは危険
データベースのテーブルを直接操作するようなAPIを作ることもできる。が、SQLを文をただ包んだだけの設計では使いやすいAPIにならない。
なぜならそんなAPIでは、データが内部的どのように格納されているか、どういうリレーションを持っているかなどを理解していないと使うことができないため。
また内部構造を公開してしまうのはセキュリティを考えても危険なこと。
エンドポイントの設計とリクエストの形式
API パス設計
ホスト名 api.example.com
の部分については大文字・小文字はもともと無視される仕様。
そのためパス名も小文字にする方が統一できる。
HTTPにおいてURIは「スキーマとホスト名を除いては大文字と区別される」と使用に書いてある。
したがって、エンドポイントを小文字としている以上大文字を入れたらエラーにするべき。
HTTPメソッドとエンドポイント
1つのURIエンドポイントに異なるメソッドでアクセスしリソースをどう扱うかをきちんと分離して扱うことができる。
GET
リソースの取得を表す。
POST
指定したURIに属する新しいリソースを送信する。
https://api.example.com/v1/friends
送信したデータは指定したURIに従属したものとなる。
従属とは下位に属する意味。
例
ディレクトリの中にファイルが入っている場合、ファイルがディレクトリに属している関係。
したがってディレクトリやカテゴリなどデータの集合を表すURIに対してPOSTを行うと、新しいデータがその配下に作られるイメージ。
PUT
更新したいリソースのURIそのものを指定し、その内容をすべて書き換える。
PUTには冪等性がある。
https://api.example.com/v1/friends/12345
PUTは送信するデータで元々のリソ ースを完全に上書きするというものになる。
一部だけ書き換えたい場合はPATCHメソッドを使用する。
PUTの冪等性(べきとうせい)とは、同じリクエストを何度繰り返しても、結果が変わらない性質のことです。具体的には、PUTメソッドを使ってリソースを作成または更新する際に、同じリクエストを複数回送ってもサーバー上のリソースの状態は変わらず、同じ状態に保たれることを指す。
例えば、PUTで特定のユーザーのプロフィール情報(名前やメールアドレス)を送信した場合は以下の通り。
- 1回目のリクエストでサーバー上のリソースが更新される。
- 2回目以降のリクエストを送っても、同じ内容であれば、サーバー上の状態はすでに更新されているため、何も変わらない。
これは、POSTとは異なり、同じリクエストを複数回送信しても状態に影響がないため、安心してリトライ可能であり、エラーが発生した場合でも再度リクエストしやすいというメリットがある。
PUTが冪等である理由は、リクエストがリソース全体を「置き換える」動作をするため
DELETE
PATCH
更新したいリソースのURIそのものを指定し、その内容を一部書き換える。
https://api.example.com/v1/friends/12345
PATCHメソッドには冪等性がないため注意。
POST以外のメソッドをPOSTを使って表現する。
HTML5の Form
ではGETとPOSTのみがサポートされている。
この制限はHTMLの歴史的な理由によるもので、他のHTTPメソッド(PUT
や DELETE
など)は form
要素では直接サポートされていない。
メタ情報として本当はこのメソッドを使いたいということをサーバーに送信する。
X-HTTP-Method-Override
のリクエストヘッダーを用いるX-HTTP-Method-Override: DELETE
_method
というフォームパラメーターを利用する方法user=testuser&_method=PUT
Ruby on Railsなどが採用している。
APIのエンドポイント設計
- 覚えやすくどんな機能を持つURIなのかが一目で分かる。
- 短く入力しやすいURI
- 人間が理解できるURI
- 改造しやすいURI
- サーバー側のアーキテクチャが反映されていないURI
- ルールが統一されたURI
https://api.example.com/v1/users # GET: ユーザー一覧の取得
https://api.example.com/v1/users # POST: ユーザーの新規登録
https://api.example.com/v1/users/:id # GET: 特定のユーザー情報の取得
https://api.example.com/v1/users/:id # PUT/PATCH: 特定のユーザー情報の更新
https://api.example.com/v1/users/:id # DELETE: 特定のユーザー情報の削除
一覧を意味するために list
とつけることがあるが、URIを見れば分かるため不要。
自分の情報のエイリアス。
自身の情報を取得する場合には /users/:id
となるが、自分の情報を知るためにIDを用いるのは不便になる場合がある。
そこで利用されているのが me
または self
というキーワード。
APIを分けることで、他人の個人情報を丸見えになってしまうバグの混入を防ぐことができる。
/users/me
エンドポイントがなぜ名詞なのか
HTTPのURIがそもそもリソースを表すものであるため。
HTTPメソッドが動詞を表すおのであれい、その組み合わせを使うことが最もシンプルに行いたいことを表すことができるため。
そのため動詞は極力エンドポイントには入れない。