モジュール 04ターム1 · 基礎4 ポスター項目
API とコントラクト
ログインすると、進捗を複数のデバイスで保存できます。ログインするまでは、このブラウザに保存されます。
なぜ重要なのか
API は約束です。モバイルアプリ、パートナー、エージェントがいったん依存し始めたら、どんな変更も、あなたからは見えない誰かを壊す可能性があります。エンタープライズの購買担当者は、API コントラクトの品質であなたを評価します。
学習目標
- OpenAPI のコントラクトに基づいて、一貫性のある REST API を設計できる。
- 状態を変更するすべてのエンドポイントを冪等にできる。
- クライアントを壊さずに API とライブラリをバージョン管理できる。
- gRPC が適したツールになるのはどんなときかを判断できる。
レッスン
4.1 コントラクトファーストの設計
- まず OpenAPI の仕様を書き、そこから型、クライアント、ドキュメント、モックサーバーを生成します。
- 一貫した規約:リソースには名詞、パスは複数形、標準的なステータスコード、カーソルベースのページネーション、ISO 8601 のタイムスタンプ。
- エラー形式はどこでも1種類(RFC 9457 Problem Details):
type、title、status、detail、それにリクエスト ID。 - 境界ですべての入力をスキーマに照らして検証し、未知のフィールドは拒否します。
- 必要以上のフィールドを返してはいけません(過剰なデータ露出は API の典型的な脆弱性です)。
4.2 Idempotency(冪等性) (14)
ネットワークは、サーバーが処理を終えた後、クライアントが応答を受け取る前に切れることがあります。クライアントはリトライします。冪等性がなければ、顧客は二重に課金されます。
パターン(Stripe によって広まったもの):
- クライアントは POST に
Idempotency-Key: <uuid>を付けて送信します。 - サーバーは、キー、リクエストのハッシュ、レスポンスを、一意制約付きのテーブルに保存します。
- 同じキーが再び来たら、保存済みのレスポンスを返し、処理を再実行しません。
- 同じキーで本文が異なる場合は、422 で拒否します。
- キーは 24 時間以上経過したら失効させます。
GET、PUT、DELETE は本来冪等であるべきです。そうなるように設計してください。
4.3 バージョニング (102, 103)
- API バージョニング: URL(
/v1/)またはヘッダーで行います。追加的な変更(新しい任意フィールド)は互換性を壊しません。フィールドの削除やリネーム、型や意味の変更は互換性を壊します。 - 非推奨化ポリシー:告知し、
DeprecationとSunsetヘッダーを付け、旧バージョンの利用状況を計測してから削除します。 - パッケージにはセマンティックバージョニング:
MAJOR.MINOR.PATCH。MAJOR は互換性を壊す変更、MINOR は機能追加、PATCH は修正です。lockfile で依存関係を固定し、他者が semver を完璧に守っていると信用しないでください。
4.4 gRPC (100)
型付き、バイナリ、高速、ストリーミング対応で、HTTP/2 上で動作します。大規模な内部のサービス間通信には最適です。ブラウザや公開 API には向きません。ソロの創業者が必要とすることはまれなので、概念として学んでおきましょう。
4.5 API セキュリティの予告
すべてのオブジェクトに対する認可(BOLA は API リスクの第1位です)、キーごとの rate limiting、ページネーションの上限、リクエストサイズの上限。詳しくは 05 · アプリケーションセキュリティ: OWASP Top 10:2025 で扱います。
Lab 4:コントラクトをリリースする
- コアとなるリソースの OpenAPI 仕様を書き、型付きクライアントを生成します。
- 決済または「注文作成」のエンドポイントに idempotency キーを追加し、同じリクエストを同時に5回送ってレコードが1件だけであることをアサートするテストを書きます。
- 互換性を壊す変更を正しい方法で行います:非推奨ヘッダーを付けた v1 と並行して v2 をリリースします。
- 実装が仕様から乖離したら、CI のコントラクトテストが失敗するようにします。
完了の定義(Definition of Done)
AI プロンプト集
- 「これらのルートから OpenAPI 3.1 の仕様を生成し、命名、ステータスコード、エラー形式の不整合を列挙してください。」
- 「このエンドポイントに、一意制約付きの Postgres テーブルで裏付けた Stripe 方式の idempotency キーを追加してください。同時に重複リクエストが来たケースにも対応してください。」