REST API 設計の実践原則
2 min read
REST API は一度公開すると変更しにくいため、設計段階での判断が重要です。後悔しないための設計原則をまとめます。
URL 設計はリソースで考える
URL はアクションではなくリソース(名詞)を表します。
# 悪い例: 動詞を使っている
GET /getUsers
POST /createUser
POST /deleteUser?id=123
# 良い例: リソース + HTTP メソッドで表現
GET /users # 一覧取得
POST /users # 作成
GET /users/123 # 1件取得
PUT /users/123 # 全体更新
PATCH /users/123 # 部分更新
DELETE /users/123 # 削除
階層関係は URL で表現します。
GET /users/123/orders # ユーザー123の注文一覧
GET /users/123/orders/456 # 特定の注文
HTTP ステータスコードを正しく使う
| コード | 意味 | 使いどころ |
|---|---|---|
| 200 | OK | 取得・更新成功 |
| 201 | Created | リソース作成成功 |
| 204 | No Content | 削除成功(ボディなし) |
| 400 | Bad Request | バリデーションエラー |
| 401 | Unauthorized | 未認証 |
| 403 | Forbidden | 認可エラー(ログイン済みだが権限なし) |
| 404 | Not Found | リソースが存在しない |
| 409 | Conflict | 重複など競合 |
| 422 | Unprocessable Entity | 意味的に不正なリクエスト |
| 500 | Internal Server Error | サーバー側の予期しないエラー |
200 をすべてに使ってエラーをボディで返すのはやめましょう。
エラーレスポンスを統一する
エラー時のレスポンス形式を統一しておくと、クライアント側の実装が楽になります。
{
"error": {
"code": "VALIDATION_ERROR",
"message": "入力値が不正です",
"details": [
{ "field": "email", "message": "有効なメールアドレスを入力してください" },
{ "field": "age", "message": "18歳以上である必要があります" }
]
}
}
code にはマシンリーダブルな文字列を入れると、クライアントがプログラムで判定できます。
バージョニング
API を公開した後に破壊的変更をする場合はバージョンを切ります。
# URL パスにバージョンを含める(最も一般的)
/v1/users
/v2/users
# ヘッダーでバージョン指定(URL をきれいに保ちたい場合)
Accept: application/vnd.myapp.v2+json
ページネーション
大量データの取得にはページネーションを必ず実装します。
# カーソルベース(SNS のような無限スクロールに向く)
GET /posts?cursor=eyJpZCI6MTAwfQ&limit=20
# オフセットベース(ページ番号指定に向く)
GET /products?page=3&per_page=20
レスポンスには次のページの情報を含めます。
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6MTIwfQ",
"has_more": true
}
}
まとめ
- URL はリソース(名詞)で設計する
- HTTP メソッドとステータスコードのセマンティクスに従う
- エラーレスポンスの形式を統一する
- 公開後の変更にはバージョニングで対応
- 一覧取得には必ずページネーションを
設計に迷ったときは「クライアントを実装する人が直感的に使えるか」を基準にすると判断しやすいです。