コンテンツにスキップ

REST API の HTTP 動詞設計の現実

原文

究極的には GET/POST/PUT/DELETE そして HEAD/OPTIONS/PATCH なんかも含めての REST なんですが、HEAD/OPTIONS あまり要件が無いのと、POST/PUT/PATCH の区別があやふやになりがちなのと、HTTP Proxy のせいで POST 以外の更新系が送れなくて(x-http-method-override: DELETE) 全部 POST にしてしまった等の、悪い過去もあり、しまいには最近の流行りなのか全部 POST にするヤンチャ系も出てきて(もはやそれは REST ではないが)、崇高な REST の設計思想は崩れ始めている。

要約

RESTはGET/POST/PUT/DELETE/PATCH等の動詞を使い分けることが原則だが、現実にはProxy制約・POST/PUT/PATCHの区別の曖昧さ・「全部POST」ヤンチャ設計等により崩れがち。mattnがRESTの設計思想の理想と現実のギャップを指摘。

解説

REST における HTTP メソッドの本来の役割

メソッド 用途 冪等性 安全性
GET リソースの取得
POST リソースの作成 / アクション実行
PUT リソースの完全置換
PATCH リソースの部分更新
DELETE リソースの削除
HEAD ヘッダーのみ取得(GETの軽量版)
OPTIONS 対応メソッドの確認(CORS等)

現実に生じる問題

1. POST / PUT / PATCH の区別の曖昧さ

  • PUT: リソース全体を送信して置換(一部省略=nullとして扱う)
  • PATCH: 変更したいフィールドだけ送信して部分更新
  • 実装が複雑になるため、チームによっては「PUTですべて」「PATCHは使わない」等の判断をすることがある

2. HTTP Proxy の制約

  • 古いProxyはPOST以外の更新系メソッドを通さないものがあった
  • 対策として x-http-method-override: DELETE ヘッダーをPOSTリクエストに付けて実際のメソッドを示す回避策が生まれた

3. 「全部POST」設計(RPCスタイル)

# RESTスタイル
DELETE /api/users/123

# 全部POSTスタイル(RPC的)
POST /api/users/delete
{ "id": 123 }
  • GraphQL / gRPC / tRPC はこのRPCスタイルの現代的な形
  • 「RESTではない」が、スキーマ定義・型安全性・ツールの充実度で実用的な選択肢になっている

現代的な選択肢

アプローチ 特徴 向いている場面
REST(厳密) HTTPメソッドを正しく使う 公開API、標準的なCRUD
REST(緩い) GET/POST中心 チーム内API、レガシー互換
GraphQL POST一択、クエリ言語 フロントが多様なデータを必要とする場合
gRPC HTTP/2 + Protocol Buffers マイクロサービス間通信

→ 関連: オフセット vs カーソルページネーションAPIゲートウェイ

リンク