REST API

HTTP メソッドとリソース指向の URL で設計する Web API のアーキテクチャスタイル

APIWeb

REST API とは

REST (Representational State Transfer) は、Roy Fielding が 2000 年の博士論文 (第 5 章) で定義した、分散ハイパーメディアシステム向けのアーキテクチャスタイルである。HTTP に固有の規格ではなく制約の組み合わせを指す名前だが、実務で「REST API」と呼ばれるものは、この制約を HTTP に当てはめて、リソース指向の URL と HTTP メソッドでデータを操作する設計慣習を指すことが多い。

6 つの制約

論文が挙げる制約は、クライアントサーバー分離、ステートレス (要求ごとに必要な情報が揃っている)、キャッシュ可能性、統一インターフェース、階層化システム、コードオンデマンドの 6 つである。最後のコードオンデマンド (クライアントへコードを配って機能を足す) だけは可視性を下げる代償があるため、論文自身が任意の制約と位置づけている。

統一インターフェースはさらに 4 点に分かれ、その 1 つが「ハイパーメディアを応用状態のエンジンとする」(HATEOAS)、つまり次に取り得る操作をサーバーが応答内のリンクで示すという要求である。実際の「REST API」はここを満たさないものが大半で、Fielding 自身も 2008 年の記事でハイパーテキスト駆動でない設計を REST と呼ぶことを否定している。段階の整理は REST 成熟度モデル を参照。

HTTP メソッドと CRUD

再送したときの振る舞いは実装の作法ではなく HTTP の仕様 (RFC 9110) で決まっている。「安全」は意味上読み取り専用であること、「べき等」は同じ要求を複数回送ってもサーバー側の意図された結果が 1 回のときと同じであることを指す。返る応答まで同一とは限らない点が要点で、たとえば DELETE の 2 回目は 404 になり得るが、消えているという結果は変わらないのでべき等である。仕様がべき等とするのは PUT、DELETE と安全なメソッドで、応答を読む前に通信が切れた場合に自動で再送してよいのはこの範囲に限られる。

メソッド操作同じ要求を再送したとき
GET取得状態を変えない (安全) ため何度でも送れるGET /users/123
POST作成呼んだ回数だけリソースが増える (べき等でない)POST /users
PUT全体更新同じ内容を送る限り、結果の状態は 1 回目と変わらないPUT /users/123
PATCH部分更新差分の書き方によって結果が変わり、同じ状態は保証されないPATCH /users/123
DELETE削除2 回目以降は消す対象が無く、状態は変わらないDELETE /users/123

べき等でない POST を安全に再送させたい決済や登録では、クライアントが発行した鍵で二重処理を弾く設計を足す (べき等性)。

URL 設計

動作を URL の動詞で表すと、キャッシュしてよいか、再送してよいか、誰に許すかといった判断の手がかりを HTTP から奪うことになる。URL には名詞 (リソース) を置き、何をするかはメソッドで表す。検索や集計のように名詞化しづらい操作は、無理に新しい動詞を作らず、従属リソース (/users/123/orders) かクエリパラメーターとして表す。

✅ リソース指向
GET    /users          ← ユーザー一覧
GET    /users/123      ← ユーザー取得
POST   /users          ← ユーザー作成
PUT    /users/123      ← ユーザー更新
DELETE /users/123      ← ユーザー削除
GET    /users/123/orders ← ユーザーの注文一覧

❌ 動詞ベース
GET /getUser?id=123
POST /createUser
POST /deleteUser

ステータスコード

コードの一覧は HTTP ステータスコード に譲り、ここでは API 設計で効く点を挙げる。201 で作ったリソースの位置は本文の説明ではなく Location ヘッダーで示す (RFC 9110)。204 は本文を返さないという約束なので、ボディに理由を書いてはいけない。エラー本文は各社各様に作らず、RFC 9457 の Problem Details 形式 (type / title / status / detail) に寄せるとクライアント側の分岐が安定する。なお 429 は RFC 9110 ではなく RFC 6585 で追加されたコードである。

コード意味用途
200OK成功
201Createdリソース作成成功
204No Content削除成功
400Bad Requestリクエストが不正
401Unauthorized認証が必要
403Forbidden権限がない
404Not Foundリソースが存在しない
429Too Many Requestsレート制限
500Internal Server Errorサーバーエラー

GraphQL との比較

どちらが優れているかではなく、画面の要求がどれだけ動くかで選ぶ。参照する項目が安定していて HTTP のキャッシュを効かせたいなら REST、画面ごとに必要な項目が変わり往復回数を削りたいなら GraphQL が向く。

観点RESTGraphQL
エンドポイントリソースごとに複数1 つ (/graphql)
データ取得固定レスポンスクライアントが選択
Over-fetching起きやすい必要な項目だけ指定して避けられる
キャッシュHTTP キャッシュが使える工夫が必要
学習コストHTTP の知識で始められるスキーマとリゾルバーの設計が前提

ページネーション

?offset=1000 型は読み飛ばす件数に比例してコストが増え、ページを送っている途中に前のページで挿入や削除が起きると、同じ行が 2 回出たり抜け落ちたりする。カーソル型は「どこまで読んだか」を不透明な文字列で持ち回るため、この崩れが起きない。

GET /users?limit=20&cursor=eyJpZCI6IjEyMyJ9

{
  "items": [...],
  "nextCursor": "eyJpZCI6IjE0MyJ9"
}

DynamoDB の Query と Scan は続きの開始位置を LastEvaluatedKey として返すため、それをそのままカーソルに変換できる。ただし中身はテーブルのキー値なので、API の契約に露出させず符号化して包む。露出させると、後でキー設計を変えた瞬間に発行済みのカーソルが壊れる。

公開範囲が広く長く使われる API ほど、HTTP の既定の意味 (キャッシュ、べき等、ステータスコード) に寄せておく価値が上がる。中間のプロキシやクライアントの標準実装がその意味を前提に動くため、独自の約束を足すほど自分で面倒を見る範囲が増える。

この記事は役に立ちましたか?

関連用語

関連する記事