ストーリー
高橋アーキテクトがホワイトボードにURLを書き始めた。
RESTの6つの制約
REST は以下の6つの制約(architectural constraints)で定義されます。
| # | 制約 | 説明 |
|---|---|---|
| 1 | クライアント・サーバー | 関心の分離。UIとデータ処理を分ける |
| 2 | ステートレス | サーバーはクライアントの状態を保持しない |
| 3 | キャッシュ可能 | レスポンスにキャッシュの可否を明示する |
| 4 | 統一インターフェース | 一貫したインターフェースでリソースを操作する |
| 5 | 階層化システム | クライアントは直接サーバーに接続しているか分からない |
| 6 | コードオンデマンド(任意) | 必要に応じてクライアントにコードを送信できる |
リソース指向の考え方
リソースとは
RESTでは、あらゆるものをリソースとして扱います。
// リソースの例
interface Resource {
// ユーザーというリソース
users: User[];
// 注文というリソース
orders: Order[];
// 商品というリソース
products: Product[];
}
// 各リソースは一意のURI(Uniform Resource Identifier)で識別される
// /users → ユーザーのコレクション
// /users/123 → ID:123のユーザー
// /users/123/orders → ID:123のユーザーの注文一覧
リソース設計の基本ルール
良い例(名詞・複数形):
GET /users → ユーザー一覧を取得
GET /users/123 → 特定のユーザーを取得
POST /users → ユーザーを作成
PUT /users/123 → ユーザーを更新
DELETE /users/123 → ユーザーを削除
悪い例(動詞を使ってしまう):
GET /getUsers → 動詞は不要(HTTPメソッドが動詞の役割)
POST /createUser → POST自体が「作成」を意味する
POST /deleteUser → DELETEメソッドを使うべき
HTTPメソッドの使い分け
5つの基本メソッド
// GET - リソースの取得(安全・冪等)
// サーバーの状態を変更しない
const response = await fetch('/api/users/123', {
method: 'GET',
});
// POST - リソースの作成(非冪等)
// 同じリクエストを2回送ると2つのリソースが作られる
const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: '田中太郎', email: 'tanaka@example.com' }),
});
// PUT - リソースの完全置換(冪等)
// 同じリクエストを何度送っても結果は同じ
const response = await fetch('/api/users/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: '田中太郎', email: 'tanaka@new.com' }),
});
// PATCH - リソースの部分更新(冪等)
// 変更したいフィールドだけ送る
const response = await fetch('/api/users/123', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'tanaka@new.com' }),
});
// DELETE - リソースの削除(冪等)
const response = await fetch('/api/users/123', {
method: 'DELETE',
});
メソッドの特性
| メソッド | 安全性 | 冪等性 | リクエストボディ | 用途 |
|---|---|---|---|---|
| GET | 安全 | 冪等 | なし | 取得 |
| POST | 非安全 | 非冪等 | あり | 作成 |
| PUT | 非安全 | 冪等 | あり | 完全置換 |
| PATCH | 非安全 | 冪等 | あり | 部分更新 |
| DELETE | 非安全 | 冪等 | なし | 削除 |
安全性: サーバーの状態を変更しない 冪等性: 同じ操作を何度実行しても結果が同じ
HTTPステータスコードの正しい使い方
主要なステータスコード
// 2xx: 成功
// 200 OK - リクエスト成功(GET, PUT, PATCH, DELETE)
// 201 Created - リソース作成成功(POST)
// 204 No Content - 成功だが返すデータなし(DELETE)
// 3xx: リダイレクト
// 301 Moved Permanently - リソースが恒久的に移動
// 304 Not Modified - キャッシュが有効
// 4xx: クライアントエラー
// 400 Bad Request - リクエストが不正
// 401 Unauthorized - 認証が必要
// 403 Forbidden - 権限がない
// 404 Not Found - リソースが見つからない
// 409 Conflict - 競合(既に存在するリソースの作成など)
// 422 Unprocessable Entity - バリデーションエラー
// 429 Too Many Requests - レート制限超過
// 5xx: サーバーエラー
// 500 Internal Server Error - サーバー内部エラー
// 502 Bad Gateway - ゲートウェイエラー
// 503 Service Unavailable - サービス一時停止
ステータスコード選択のフローチャート
リクエストは正しい?
├── No → 400 Bad Request
└── Yes → 認証されている?
├── No → 401 Unauthorized
└── Yes → 権限がある?
├── No → 403 Forbidden
└── Yes → リソースは存在する?
├── No → 404 Not Found
└── Yes → 処理成功?
├── No → 500 Internal Server Error
└── Yes → 200/201/204
ステートレスの原則
ステートレスとは
// 悪い例: サーバーがセッション状態を保持
// リクエスト1: ログイン
POST /login { username: "tanaka" }
// → サーバーがセッションを作成(ステートフル)
// リクエスト2: データ取得(セッションに依存)
GET /my-data
// → サーバーがセッションからユーザーを特定
// 良い例: 毎回認証情報を含める(ステートレス)
// リクエスト1: データ取得
GET /api/users/123
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
// → トークンからユーザーを特定(サーバーに状態なし)
// リクエスト2: データ更新
PUT /api/users/123
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
// → 同じトークンで認証(各リクエストが独立)
ステートレスのメリット
| メリット | 説明 |
|---|---|
| スケーラビリティ | どのサーバーでもリクエストを処理できる |
| 信頼性 | サーバー障害時に別サーバーで処理を継続できる |
| シンプルさ | サーバーがセッション管理する必要がない |
まとめ
| ポイント | 内容 |
|---|---|
| RESTの本質 | HTTPプロトコルの上にリソース指向のAPIを構築するスタイル |
| リソース指向 | 名詞・複数形のURIでリソースを識別する |
| HTTPメソッド | GET/POST/PUT/PATCH/DELETEで操作を表現する |
| ステータスコード | 適切なコードでクライアントに結果を伝える |
| ステートレス | サーバーはクライアントの状態を保持しない |
チェックリスト
- RESTの6つの制約を理解した
- リソース指向のURI設計ルールを把握した
- HTTPメソッドの使い分け(安全性・冪等性)を理解した
- 主要なHTTPステータスコードを把握した
- ステートレスの原則とメリットを理解した
次のステップへ
RESTの基本原則を学びました。
次のセクションでは、良いAPIと悪いAPIを実例で比較します。 理論だけでなく、実際に「どう設計すべきか」を具体例で体感しましょう。
推定読了時間: 25分