第1部:アプリケーション設計 Step 3 / 24

API設計

REST APIは、フロントエンドとバックエンドをつなぐ重要なインターフェース。一貫性のある設計がアプリの品質を左右します。

RESTful API設計の基本

HTTPメソッドとCRUD

メソッド 操作 説明
GET Read(取得) GET /posts 記事一覧を取得
POST Create(作成) POST /posts 新規記事を作成
PUT Update(更新) PUT /posts/1 記事を全体更新
PATCH Update(部分更新) PATCH /posts/1 記事を部分更新
DELETE Delete(削除) DELETE /posts/1 記事を削除

URL設計のルール

/posts 複数形の名詞を使う
/getPost, /createPost 動詞は使わない
/posts/1/comments 関連リソースは階層で表現
/posts?page=1&limit=10 フィルタ・ページングはクエリパラメータ

ブログアプリのAPI設計

認証API

エンドポイント 説明 認証
POST /auth/register ユーザー新規登録 不要
POST /auth/login ログイン(トークン発行) 不要
GET /auth/me 現在のユーザー情報 必要

記事API

エンドポイント 説明 認証
GET /posts 記事一覧取得 不要
GET /posts/:id 記事詳細取得 不要
POST /posts 記事作成 必要
PUT /posts/:id 記事更新 必要(本人のみ)
DELETE /posts/:id 記事削除 必要(本人のみ)

リクエストとレスポンスの例

POST /auth/register - ユーザー登録

リクエスト

{
  "email": "user@example.com",
  "password": "securepassword",
  "name": "山田太郎"
}

レスポンス(201 Created)

{
  "id": 1,
  "email": "user@example.com",
  "name": "山田太郎",
  "createdAt": "2024-01-15T10:30:00Z"
}

POST /auth/login - ログイン

リクエスト

{
  "email": "user@example.com",
  "password": "securepassword"
}

レスポンス(200 OK)

{
  "access_token": "eyJhbGciOiJ...",
  "token_type": "bearer"
}

GET /posts - 記事一覧

レスポンス(200 OK)

{
  "posts": [
    {
      "id": 1,
      "title": "はじめての投稿",
      "content": "これは最初の記事です...",
      "author": {
        "id": 1,
        "name": "山田太郎"
      },
      "createdAt": "2024-01-15T10:30:00Z",
      "updatedAt": "2024-01-15T10:30:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 10
}

HTTPステータスコード

成功(2xx)

  • 200 OK - 成功
  • 201 Created - 作成成功
  • 204 No Content - 削除成功

エラー(4xx, 5xx)

  • 400 Bad Request - リクエスト不正
  • 401 Unauthorized - 認証必要
  • 403 Forbidden - 権限なし
  • 404 Not Found - 見つからない
  • 500 Internal Error - サーバーエラー

FastAPIでの実装例

from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel

app = FastAPI()

# リクエスト/レスポンスの型定義
class PostCreate(BaseModel):
    title: str
    content: str

class PostResponse(BaseModel):
    id: int
    title: str
    content: str
    author_id: int
    created_at: datetime

# 記事一覧
@app.get("/posts", response_model=list[PostResponse])
def get_posts(page: int = 1, limit: int = 10):
    # データベースから記事を取得
    return posts

# 記事詳細
@app.get("/posts/{post_id}", response_model=PostResponse)
def get_post(post_id: int):
    post = get_post_by_id(post_id)
    if not post:
        raise HTTPException(status_code=404, detail="Post not found")
    return post

# 記事作成(認証必要)
@app.post("/posts", response_model=PostResponse, status_code=201)
def create_post(post: PostCreate, current_user = Depends(get_current_user)):
    new_post = create_post_in_db(post, current_user.id)
    return new_post

# 記事削除(本人のみ)
@app.delete("/posts/{post_id}", status_code=204)
def delete_post(post_id: int, current_user = Depends(get_current_user)):
    post = get_post_by_id(post_id)
    if not post:
        raise HTTPException(status_code=404, detail="Post not found")
    if post.author_id != current_user.id:
        raise HTTPException(status_code=403, detail="Not authorized")
    delete_post_from_db(post_id)
    return None

まとめ

  • HTTPメソッドを適切に使い分ける(GET, POST, PUT, DELETE)
  • URLは複数形の名詞を使う(/posts, /users)
  • 適切なステータスコードを返す
  • 認証が必要なエンドポイントを明確にする
コンポーネント設計 次へ:データベース設計