Open7

WEB APIデザイン

羊飼い羊飼い

設計ポイント

  1. APIのエンドポイント設計(例:/users, /products)。
  2. リクエストとレスポンスの形式(JSON、XMLなど)を決定する。
  3. データベースの設計(テーブルやスキーマの定義)。
  4. 認証と認可の方法を決める(例:OAuth、APIキー)。
羊飼い羊飼い

1. APIのエンドポイント設計

エンドポイントの設計についての詳細は以下の通りです。

基本的な設計ポイント

  1. リソースベースの設計:

    • エンドポイントはリソースに基づいて設計します。例えば、ユーザー情報を管理するAPIなら、/usersというエンドポイントを持つことが一般的です。
    • エンドポイントや操作を明確に定義するためのアプローチです。
  2. HTTPメソッドの適切な使用:

    • GET: データの取得(例:GET /usersで全ユーザーの一覧取得)。
    • POST: データの作成(例:POST /usersで新規ユーザーの作成)。
    • PUT: データの更新(例:PUT /users/123でユーザーID 123の情報更新)。
    • DELETE: データの削除(例:DELETE /users/123でユーザーID 123の削除)。
  3. 階層的なURL設計:

    • 関連するリソースは階層的に設計します(例:/users/123/ordersでユーザーID 123の注文一覧取得)。
  4. ステータスコードの適切な使用:

    • 200 OK: 成功したリクエスト。
    • 201 Created: 新しいリソースが作成された。
    • 400 Bad Request: クライアントからの不正なリクエスト。
    • 401 Unauthorized: 認証が必要。
    • 404 Not Found: リソースが見つからない。
    • 500 Internal Server Error: サーバーの内部エラー。

ソフトウェア品質に関わる点

  1. 一貫性:

    • エンドポイントの命名規則やURLの設計が一貫していることは、APIの使いやすさに直結します。
  2. ドキュメント:

    • 詳細なAPIドキュメントを提供し、エンドポイントの使用方法を明確にします。SwaggerやPostmanを使用してドキュメントを自動生成するのも有効です。
  3. セキュリティ:

    • API認証と認可の実装(例:OAuth2、APIキー)。
    • HTTPSの使用。
    • 入力データのバリデーションとサニタイズ。
  4. パフォーマンス:

    • 適切なキャッシュ制御(例:HTTPキャッシュヘッダの設定)。
    • ページネーションの実装(例:GET /users?page=2&limit=50)。
      一貫性:

エンドポイントの命名規則や設計が一貫していることで、APIの使いやすさが向上します。
一貫性のあるレスポンスフォーマットを提供することで、クライアント側の実装が容易になります。
可読性:

エンドポイントが直感的で分かりやすい命名を持つことで、開発者がAPIの機能を理解しやすくなります。
拡張性:

リソースベースの設計は、新しいリソースや機能の追加が容易です。例えば、新しいリソースを追加する場合、そのエンドポイントを定義するだけで済みます。

ベストプラクティス

  1. バージョニング:

    • APIの変更に備え、URLにバージョンを含める(例:/api/v1/users)。
  2. エラーメッセージの詳細化:

    • 明確で理解しやすいエラーメッセージを提供する。
  3. フェイルセーフ:

    • APIが一部の障害に対しても動作し続けられるように設計する。
  4. RESTful設計:

    • RESTの原則に従う(例:ステートレス性、統一インターフェース)。
  5. HATEOAS(Hypermedia as the Engine of Application State):

    • レスポンスにリンクを含めることで、クライアントが次に取るべきアクションをガイドします。
  6. メトリクスとロギング:

    • APIの使用状況やエラーログを収集し、分析できるようにする。

これらのポイントに注意することで、使いやすく、信頼性が高く、保守しやすいWeb APIを設計・実装することができます。

羊飼い羊飼い

2. リクエストとレスポンスの形式の決定

基本的な設計ポイント

  1. データ形式の選定:

    • 一般的にはJSONが使用されます。軽量で読みやすく、ほとんどのプログラミング言語でサポートされています。
    • 必要に応じてXMLや他の形式を使用することもありますが、標準化を図るためにはJSONが推奨されます。
  2. コンテンツタイプの指定:

    • リクエストヘッダーでContent-Typeを指定します(例:Content-Type: application/json)。
    • レスポンスヘッダーでも同様にContent-Typeを指定します。
  3. 標準的なレスポンス構造:

    • 一貫性のあるレスポンス構造を設計します。例えば、以下のような形式を採用します。
      {
        "status": "success",
        "data": { ... },
        "message": "Operation successful"
      }
      
    • エラーレスポンスも統一された形式にします。
      {
        "status": "error",
        "error": {
          "code": 400,
          "message": "Invalid request"
        }
      }
      
  4. 適切なステータスコードの使用:

    • レスポンスには適切なHTTPステータスコードを含めます。例えば、成功時には200、リソースの作成時には201、クライアントエラー時には400などを使用します。

ソフトウェア品質に関わる点

  1. 一貫性:

    • リクエストとレスポンスの形式が一貫していることは、APIの使いやすさと理解のしやすさに大きく寄与します。
    • 一貫したエラーメッセージとステータスコードの使用は、デバッグや問題解決を容易にします。
  2. バリデーション:

    • 入力データのバリデーションはクライアント側だけでなく、サーバー側でも行うべきです。
    • バリデーションエラーの場合は、詳細なエラーメッセージを返すようにします。
  3. セキュリティ:

    • 入力データをサニタイズして、インジェクション攻撃を防ぎます。
    • 認証情報やセンシティブなデータは、適切に暗号化して送信します。
  4. パフォーマンス:

    • データのサイズを最小限に抑えるために、不要なフィールドを削除したり、レスポンスの圧縮を行います。
    • キャッシュ制御を適切に行い、パフォーマンスを向上させます。

ベストプラクティス

  1. ドキュメンテーション:

    • リクエストとレスポンスのフォーマットを詳細にドキュメント化します。
    • SwaggerやOpenAPIを使用して、自動生成されたAPIドキュメントを提供します。
  2. バージョニング:

    • APIのバージョニングを行い、将来的な変更に対応できるようにします。例えば、/api/v1/resourceのようにバージョン番号をURLに含めます。
  3. ハイパーメディアリンクの使用:

    • HATEOAS(Hypermedia as the Engine of Application State)を導入し、レスポンスに次の操作を示すリンクを含めます。
  4. 例外処理:

    • サーバー側で発生した例外を適切にハンドリングし、詳細なエラーメッセージをクライアントに返します。
    • ログを記録して、後で問題を診断しやすくします。
  5. 国際化とローカライゼーション:

    • 必要に応じて、エラーメッセージやレスポンスメッセージを複数の言語で提供できるように設計します。

これらのポイントに従うことで、使いやすく、信頼性が高く、メンテナンスしやすいWeb APIを設計・実装することができます。

羊飼い羊飼い

3. データベースの設計

基本的な設計ポイント

  1. 要件定義:

    • データベースに保存する必要があるデータを明確に定義します。
    • データの関係性(リレーションシップ)を把握します。
  2. 正規化:

    • データの冗長性を減らし、一貫性を保つために正規化を行います。
    • 第三正規形(3NF)まで正規化することが一般的です。
  3. エンティティと属性の定義:

    • 各エンティティ(テーブル)を定義し、それぞれの属性(カラム)を決定します。
    • 例えば、ユーザー情報を保存するテーブルなら、usersテーブルにid, name, email, passwordなどのカラムを含めます。
  4. 主キーと外部キーの設定:

    • 各テーブルに主キー(Primary Key)を設定します。
    • 外部キー(Foreign Key)を使用して、他のテーブルとの関係を定義します。
  5. インデックスの設定:

    • クエリのパフォーマンスを向上させるために、適切なカラムにインデックスを設定します。
  6. データ型の選定:

    • 各カラムに適切なデータ型を選定します。例えば、整数型、文字列型、日付型など。

ソフトウェア品質に関わる点

  1. データの一貫性:

    • トランザクションを使用して、データの整合性を保ちます。
    • ACID特性(Atomicity, Consistency, Isolation, Durability)を遵守します。
  2. スキーマのバージョニング:

    • スキーマの変更を管理するために、マイグレーションツールを使用します。例えば、FlywayやLiquibaseなど。
    • スキーマのバージョン管理を行い、変更履歴を追跡できるようにします。
  3. パフォーマンス:

    • クエリの最適化を行い、パフォーマンスを向上させます。
    • 大量データのインポートやエクスポートのパフォーマンスを考慮します。
  4. セキュリティ:

    • データベースへのアクセスを制御し、適切な認証と認可を設定します。
    • センシティブなデータは暗号化して保存します。

ベストプラクティス

  1. 正規化と非正規化のバランス:

    • データの一貫性を保つために正規化を行いますが、パフォーマンスが必要な場合は非正規化も検討します。
  2. リレーションシップの明確化:

    • エンティティ間のリレーションシップを明確にし、ER図(エンティティ・リレーションシップ図)を作成します。
    • リレーションシップには一対多、多対多などがあります。
  3. リファクタリング:

    • データベーススキーマを定期的に見直し、必要に応じてリファクタリングを行います。
  4. データベースマイグレーション:

    • データベースの変更を安全に実施するために、マイグレーションツールを使用します。
    • マイグレーションスクリプトをバージョン管理システムで管理します。
  5. バックアップとリカバリ:

    • 定期的なバックアップを行い、データの損失に備えます。
    • リカバリ手順をドキュメント化し、テストします。
  6. 監視とモニタリング:

    • データベースのパフォーマンスを監視し、異常を検知するためのツールを導入します。
    • ログを収集して分析し、問題の早期発見と解決に役立てます。

具体例

以下に、ユーザー情報を管理するデータベース設計の例を示します。

テーブル設計

  • usersテーブル:

    • id: INTEGER, 主キー, オートインクリメント
    • name: VARCHAR(255)
    • email: VARCHAR(255), 一意制約
    • password: VARCHAR(255)
    • created_at: TIMESTAMP
    • updated_at: TIMESTAMP
  • ordersテーブル:

    • id: INTEGER, 主キー, オートインクリメント
    • user_id: INTEGER, 外部キー, users.idに参照
    • product_id: INTEGER
    • quantity: INTEGER
    • total_price: DECIMAL(10, 2)
    • created_at: TIMESTAMP
    • updated_at: TIMESTAMP

ER図の例

+------------+       +------------+
|   users    |       |   orders   |
+------------+       +------------+
| id         |<----->| user_id    |
| name       |       | product_id |
| email      |       | quantity   |
| password   |       | total_price|
| created_at |       | created_at |
| updated_at |       | updated_at |
+------------+       +------------+

このようにして、ユーザーと注文の関係を明確にし、データの一貫性と整合性を保つ設計を行います。

羊飼い羊飼い

4.認証と認可

基本的な設計ポイント

  1. 認証(Authentication):

    • 認証はユーザーの身元を確認するプロセスです。代表的な方法には、APIキー、OAuth、JWT(JSON Web Token)などがあります。
  2. 認可(Authorization):

    • 認可は認証されたユーザーがどのリソースにアクセスできるかを制御するプロセスです。
APIキー
  • 概要: クライアントがAPIにアクセスするための一意のキーを使用します。
  • メリット: 簡単に実装できる。
  • デメリット: キーが漏洩した場合にセキュリティリスクが高まる。
OAuth 2.0
  • 概要: クライアントが第三者のリソースにアクセスするための標準プロトコルです。
  • フロー:
    1. Authorization Code Flow: Webアプリケーションで使用され、ユーザーがリソース所有者としてログインする。
    2. Implicit Flow: SPA(シングルページアプリケーション)で使用され、アクセストークンが直接クライアントに返される。
    3. Resource Owner Password Credentials Flow: 信頼できるクライアントで使用され、ユーザーのパスワードを直接送信する。
    4. Client Credentials Flow: マシン間通信で使用され、クライアントが自分自身を認証する。
JWT(JSON Web Token)
  • 概要: 認証情報を含むトークンを使用し、クライアントとサーバー間でやり取りします。
  • メリット: ステートレスな認証を実現できる。スケーラビリティが高い。
  • デメリット: トークンが長期間有効な場合、リスクが高まる。

ソフトウェア品質に関わる点

  1. セキュリティ:

    • データの保護とユーザーのプライバシーを確保するために、認証と認可は非常に重要です。
    • 強力な暗号化アルゴリズムを使用し、通信はHTTPSを使用する。
  2. スケーラビリティ:

    • ステートレスな認証(例:JWT)を使用することで、スケーラビリティを向上させることができます。
    • トークンのリフレッシュ機構を実装して、セッション管理を行います。
  3. ユーザビリティ:

    • ユーザーが簡単に認証情報を管理できるようにする。
    • 失敗した認証試行に対して適切なエラーメッセージを提供する。
  4. メンテナビリティ:

    • 認証と認可のロジックを分離し、独立したモジュールとして管理する。
    • APIキーやトークンの管理機能を提供し、必要に応じて再生成や無効化を行えるようにする。

ベストプラクティス

  1. 強力なパスワードポリシー:

    • 強力なパスワードの作成をユーザーに求め、定期的にパスワードを変更するように促す。
  2. 多要素認証(MFA):

    • ユーザーがログイン時に追加の認証ステップ(例:SMSコード、認証アプリ)を必要とする多要素認証を導入する。
  3. トークンの管理:

    • トークンの有効期限を設定し、短期間の有効期限を推奨する。
    • トークンのリフレッシュ機能を実装する。
  4. APIキーの管理:

    • APIキーの発行、再生成、無効化の機能を提供する。
    • 各APIキーの使用状況をモニタリングし、不正な使用を検知する。
  5. ログとモニタリング:

    • 認証と認可のイベントを詳細にログに記録し、異常な活動を監視する。
    • リアルタイムでアラートを設定し、不正アクセスを迅速に検知する。
  6. 最小特権の原則:

    • ユーザーやクライアントに必要最低限の権限のみを付与し、過剰な権限を与えない。

具体例

以下に、JWTを使用した認証フローの例を示します。

JWT認証フロー
  1. ユーザー認証:

    • クライアントがユーザーの認証情報(例:ユーザー名とパスワード)をサーバーに送信。
    • サーバーが認証情報を検証し、ユーザーが正当であることを確認。
  2. トークン発行:

    • サーバーがJWTを生成し、クライアントに返す。
    • トークンにはユーザーIDや有効期限などの情報が含まれる。
  3. APIリクエスト:

    • クライアントは認証されたAPIリクエストのヘッダーにJWTを含める(例:Authorization: Bearer <token>)。
    • サーバーがJWTを検証し、リクエストを処理。
  4. トークンのリフレッシュ:

    • トークンが期限切れになる前に、クライアントがリフレッシュトークンを使用して新しいトークンを取得。

このようにして、セキュアでスケーラブルな認証と認可のシステムを構築することができます。

羊飼い羊飼い

リソースベースの設計(Resource-based Design)

エンドポイントや操作を明確に定義するためのアプローチです。以下に、リソースベースの設計について詳しく解説します。
リソースベースの設計は、APIの使いやすさ、拡張性、メンテナンス性を向上させるための重要なアプローチです。リソースを明確に定義し、適切なエンドポイントを設計することで、直感的で一貫性のあるAPIを提供できます。また、RESTの原則に従い、HTTPメソッドとステータスコードを適切に使用することで、クライアントとサーバー間の通信がスムーズに行えるようになります。

基本的な概念

  1. リソース:

    • リソースは、APIが操作する対象となるデータエンティティです。例として、ユーザー、商品、注文などがあります。
    • 各リソースは一意の識別子(通常はID)を持ちます。
  2. エンドポイント:

    • リソースにアクセスするためのURLです。例えば、/users/products/ordersなどがエンドポイントとして定義されます。
  3. HTTPメソッド:

    • リソースに対する操作をHTTPメソッドを使って指定します。主に以下のメソッドが使用されます。
      • GET: リソースの取得
      • POST: 新しいリソースの作成
      • PUT: 既存リソースの更新
      • DELETE: リソースの削除

基本的な設計ポイント

  1. リソースの識別:

    • どのデータがリソースとして扱われるべきかを決定します。リソースは具体的で自己完結的なものとします。
  2. エンドポイントの設計:

    • 各リソースに対するエンドポイントを一貫性を持って設計します。
    • 一般的な形式は、/resource/resource/{id}です。
  3. リソースの関係:

    • リソース間の関係を明確にします。例えば、ユーザーとその注文の関係を/users/{userId}/ordersのように表現します。
  4. HTTPメソッドの適切な使用:

    • 各操作に適切なHTTPメソッドを使用します。データの取得にはGET、新規作成にはPOST、更新にはPUT、削除にはDELETEを使用します。

ソフトウェア品質に関わる点

  1. 一貫性:

    • エンドポイントの命名規則や設計が一貫していることで、APIの使いやすさが向上します。
    • 一貫性のあるレスポンスフォーマットを提供することで、クライアント側の実装が容易になります。
  2. 可読性:

    • エンドポイントが直感的で分かりやすい命名を持つことで、開発者がAPIの機能を理解しやすくなります。
  3. 拡張性:

    • リソースベースの設計は、新しいリソースや機能の追加が容易です。例えば、新しいリソースを追加する場合、そのエンドポイントを定義するだけで済みます。

ベストプラクティス

  1. RESTful原則の遵守:

    • RESTの原則に従ってリソースベースの設計を行います。これには、ステートレスな通信、統一インターフェース、リソースの明確な表現などが含まれます。
  2. 階層的なリソース設計:

    • 関連するリソースは階層的に設計します。例えば、ユーザーとその注文は/users/{userId}/ordersのように表現します。
  3. 適切なHTTPステータスコードの使用:

    • 各操作の結果に対して適切なHTTPステータスコードを返すことで、クライアントに明確なフィードバックを提供します。
  4. フィルタリング、ソート、ページネーション:

    • リソースのリストを取得する際には、フィルタリング、ソート、ページネーションをサポートすることで、柔軟で効率的なデータアクセスを提供します。

具体例

以下に、リソースベースの設計の具体例を示します。

ユーザーリソースの設計

  • エンドポイント:
    • GET /users: 全ユーザーの一覧を取得
    • POST /users: 新規ユーザーを作成
    • GET /users/{id}: 特定のユーザーの詳細を取得
    • PUT /users/{id}: 特定のユーザーを更新
    • DELETE /users/{id}: 特定のユーザーを削除

注文リソースの設計

  • エンドポイント:
    • GET /orders: 全注文の一覧を取得
    • POST /orders: 新規注文を作成
    • GET /orders/{id}: 特定の注文の詳細を取得
    • PUT /orders/{id}: 特定の注文を更新
    • DELETE /orders/{id}: 特定の注文を削除

ユーザーと注文の関係

  • エンドポイント:
    • GET /users/{userId}/orders: 特定のユーザーの全注文を取得
    • POST /users/{userId}/orders: 特定のユーザーの新規注文を作成
    • GET /users/{userId}/orders/{orderId}: 特定のユーザーの特定の注文を取得

まとめ

羊飼い羊飼い

HTTPメソッドは、Web APIにおいてリソースに対する操作を定義するための重要な要素です。それぞれのメソッドには特定の役割があり、適切に使用することでAPIの使いやすさと一貫性が向上します。以下に、主要なHTTPメソッドの適切な使用について詳しく解説します。

主なHTTPメソッドとその用途

  1. GET:

    • 用途: リソースの取得
    • 使用例:
      • GET /users: 全ユーザーの一覧を取得
      • GET /users/{id}: 特定のユーザーの詳細を取得
    • 特性:
      • 安全(Safe): このメソッドの呼び出しはデータの変更を伴わない
      • 冪等(Idempotent): 同じリクエストを何度繰り返しても結果は変わらない
  2. POST:

    • 用途: 新しいリソースの作成
    • 使用例:
      • POST /users: 新規ユーザーを作成
      • POST /orders: 新しい注文を作成
    • 特性:
      • 安全でない(Not Safe): データの変更が行われる
      • 冪等でない(Not Idempotent): 同じリクエストを繰り返すとリソースが重複して作成される
  3. PUT:

    • 用途: 既存リソースの更新または新規作成(指定したリソースが存在しない場合)
    • 使用例:
      • PUT /users/{id}: 特定のユーザーの情報を更新
      • PUT /products/{id}: 商品情報を更新
    • 特性:
      • 安全でない(Not Safe): データの変更が行われる
      • 冪等(Idempotent): 同じリクエストを何度繰り返しても結果は変わらない
  4. PATCH:

    • 用途: 既存リソースの部分更新
    • 使用例:
      • PATCH /users/{id}: 特定のユーザーの一部情報を更新
      • PATCH /orders/{id}: 注文の一部情報を更新
    • 特性:
      • 安全でない(Not Safe): データの変更が行われる
      • 冪等(Idempotent): 同じリクエストを何度繰り返しても結果は変わらない
  5. DELETE:

    • 用途: リソースの削除
    • 使用例:
      • DELETE /users/{id}: 特定のユーザーを削除
      • DELETE /orders/{id}: 特定の注文を削除
    • 特性:
      • 安全でない(Not Safe): データの変更が行われる
      • 冪等(Idempotent): 同じリクエストを何度繰り返しても結果は変わらない

HTTPメソッドの適切な使用のポイント

  1. 適切なメソッドの選択:

    • 操作の目的に応じて適切なHTTPメソッドを選択します。例えば、データの取得にはGET、新規作成にはPOSTを使用します。
  2. 一貫性:

    • 同じ種類の操作には一貫したメソッドを使用します。例えば、全リソースの削除操作は常にDELETEを使用します。
  3. メソッドの特性を理解:

    • 各メソッドの特性(安全性、冪等性)を理解し、それに基づいて適切なメソッドを使用します。

ソフトウェア品質に関わる点

  1. 冪等性:

    • 冪等性の原則を守ることで、ネットワークエラーや再試行による不整合を防ぎます。PUTDELETEは冪等であるため、リクエストを再送しても同じ結果が得られる設計にします。
  2. エラーハンドリング:

    • 各HTTPメソッドに対して適切なエラーレスポンスを返すように設計します。例えば、GET /users/{id}で存在しないユーザーIDが指定された場合には404 Not Foundを返します。
  3. セキュリティ:

    • データの変更を伴う操作には適切な認証と認可を実装します。例えば、POSTPUTDELETEリクエストにはトークンベースの認証を要求します。

ベストプラクティス

  1. 明確なAPIドキュメント:

    • 各エンドポイントでサポートされるHTTPメソッドを明確に記載したAPIドキュメントを提供します。Swaggerなどのツールを使って自動生成するのも良い方法です。
  2. HTTPメソッドの適切な使用例を提供:

    • クライアント開発者が正しくメソッドを使用できるように、具体的な使用例を提供します。
  3. ステータスコードの適切な使用:

    • 各HTTPメソッドのレスポンスに適切なステータスコードを使用します。例えば、POSTリクエストが成功した場合には201 Createdを返し、GETリクエストが成功した場合には200 OKを返します。

具体例

ユーザーリソースの例

  • GET: ユーザーの一覧を取得

    • GET /users
    • レスポンス: 200 OK
    [
      {
        "id": 1,
        "name": "Alice",
        "email": "alice@example.com"
      },
      {
        "id": 2,
        "name": "Bob",
        "email": "bob@example.com"
      }
    ]
    
  • POST: 新しいユーザーを作成

    • POST /users
    • リクエストボディ:
    {
      "name": "Charlie",
      "email": "charlie@example.com",
      "password": "securepassword"
    }
    
    • レスポンス: 201 Created
    {
      "id": 3,
      "name": "Charlie",
      "email": "charlie@example.com"
    }
    
  • PUT: 特定のユーザーを更新

    • PUT /users/3
    • リクエストボディ:
    {
      "name": "Charlie",
      "email": "charlie_new@example.com",
      "password": "newsecurepassword"
    }
    
    • レスポンス: 200 OK
    {
      "id": 3,
      "name": "Charlie",
      "email": "charlie_new@example.com"
    }
    
  • DELETE: 特定のユーザーを削除

    • DELETE /users/3
    • レスポンス: 204 No Content

このように、適切なHTTPメソッドを使用することで、APIの操作が直感的で一貫性のあるものになります。また、クライアントとサーバー間の通信がスムーズになり、データの整合性とセキュリティが向上します。