(まとめ)REST APIの基礎

REST APIの基礎的な内容についてまとめてみました!

1. RESTについて

1.1 まずWeb APIとは

Web API(Web Application Programming Interface)とは、HTTPなどのWeb技術を応用して、異なるソフトウェアやアプリケーション間で情報をやり取りできるようにする仕組みのことを言います。

具体的には、一つのアプリケーションが他のアプリケーションの機能やデータにアクセスするための手段や方法を提供しています。

Web APIの代表例には、「Google Map API」や「Twitter API」などがあります。

1.2 RESTの意味と概念

REST(Representational State Transfer)は、Web上でデータや機能を提供・利用するための設計スタイルの一つで、Web APIの設計手法として定番です。

RESTの考え方の中心は、ROA(リソース指向アーキテクチャと呼ばれるもので、「リソース」を中心に設計する方法を取ります。

1.3 ROA(リソース指向アーキテクチャ

ROA(リソース指向アーキテクチャは「リソース」を中心に設計する方法です。

リソース」とは、具体的な「データ」や「動作」「概念」など、サービスが提供する「もの」全てを指します。(例:APIで提供したい「ユーザー」や「商品」など)

ROAの主な特性として以下の4つが挙げられます。

  1. アドレス可能性(Addressability): それぞれのリソースが一意のURIで表されること。
  2. ステートレス性(Statelessness): 一つひとつのリクエストが独立して処理されること。
  3. 統一インターフェース(Uniformed Interface): すべてのサービスが同じHTTPメソッドを使って操作されること。(例:データ取得であれば「GET」を使う)
  4. 接続性(Connectedness): 関連するリソース同士がお互いのURIを参照し合うこと。

リソース中心の設計方法をとることで、直観的で統一感のあるAPIを設計することが可能になります。(一意で明確なURIを持ち、統一されたHTTPメソッドを使用するなどの特性によって)

そしてREST自体もこのROAの思想を取り入れているため、RESTfulなAPIは「直観的で統一感のあるAPI」であると言えます。

2. REST原則

ROAと同様、「リソース」を中心とするRESTにはROAと類似するものを含めたいくつかの原則が存在します。

そしてこれらの原則を全て(あるいは部分的に)満たしたAPIのことをRESTful APIREST API)と呼びます。(※実際の定義は柔軟。最も重要なのは、APIの使用者にとってわかりやすく、効率的なAPIであること)

2.1 クライアント/サーバー構造

特徴:

  • クライアントとサーバーは別々の役割を持ち、独立して動作します。
  • クライアントとサーバーの間の通信は、定義されたインターフェースを通じて行われるため、一貫性が保たれます。

メリット:

  • 拡張性: クライアントやサーバーのどちらかを独立してアップグレードまたは変更することが容易になります。
  • メンテナンスの容易性: 特定の部分(クライアントまたはサーバー)のみを修正することができるため、全体のダウンタイムを最小限に抑えることができます。
  • 専門化: クライアントはユーザー体験の最適化に焦点を当て、サーバーはデータの処理やビジネスロジックに特化することができます。

デメリット:

  • 通信オーバーヘッド: クライアントとサーバー間の通信が必要になるため、ネットワークの遅延やオーバーヘッドが生じる可能性があります。
  • 複雑性の増加: クライアントとサーバーが独立して動作するため、通信やデータの同期に関する複雑性が増加する場合があります。
  • セキュリティ懸念: クライアントとサーバー間の通信はセキュリティの脅威となる可能性があり、適切な暗号化や認証が必要です。

2.2 ステートレス性

  • ステートレス (Stateless):

    特徴:

    • サーバーはクライアントの以前の活動や履歴を覚えていません。
    • クライアントが何かを要求するたびに、全ての必要な情報を毎回提供する必要があります。

    メリット:

    • 拡張性: クライアントの状態を保存しないため、サーバーが要求に応じて迅速に拡張できます。
    • 単純性: セッション情報を管理する必要がないため、設計と実装がシンプルになります。
    • 予測可能性: 同じリクエストは常に同じレスポンスをもたらすため、動作が予測可能です。

    デメリット:

    • 冗長性: クライアントが毎回全ての情報を提供する必要があるため、通信が冗長になることがあります。
    • パーソナライズが困難: クライアントの前回の状態や選択を知らないため、パーソナライズされた体験が難しくなることがあります。
  • ステートフル (Stateful):

    特徴:

    • サーバーはクライアントの以前の活動や履歴を覚えています。

    メリット:

    • 効率性: サーバーがクライアントの状態を覚えているため、クライアントが毎回同じ情報を提供する手間が省かれます。
    • パーソナライズ: クライアントの過去の選択や嗜好を基に、カスタマイズされたサービスや体験を提供することができます。

    デメリット:

    • 拡張性の問題: セッション情報やクライアントの状態を維持する必要があるため、システムのスケーラビリティに制約が生じることがあります。
    • 複雑性: クライアントの状態を管理するための追加のロジックやストレージが必要となり、システムが複雑になることがあります。

2.3 キャッシュ可能性

特徴:

  • クライアントはレスポンスデータをキャッシュして再利用することができます。
  • これにより、同じデータの再度のリクエストを減少させることができます。

メリット:

  • 効率性: サーバーへの再リクエストを避けることで、効率が上がります。
  • 高速な応答: キャッシュされたデータを使用することで、より迅速なレスポンスを提供することができます。

デメリット:

  • 古いデータ: キャッシュのデータが古くなると、ユーザーが最新の情報を取得できなくなる可能性があります。
  • 管理の複雑性: キャッシュの有効期限や更新に関する管理が必要になります。

2.4 階層システム

特徴:

  • システムは複数の層(レイヤー)で構成されます。
  • クライアントは直接最終的なサーバーにアクセスするのではなく、中間のレイヤーを通じてアクセスする場合があります。

メリット:

  • 拡張性: 新しい層の追加や既存の層の変更が容易になります。
  • 再利用性: 各レイヤーが独立して動作するため、一部のレイヤーを他のプロジェクトやシステムで再利用することができます。
  • セキュリティ: 特定のレイヤーでセキュリティポリシーや認証を施行することができます。

デメリット:

  • パフォーマンスの問題: クライアントとサーバー間の複数のレイヤーを通過することで、一定の遅延が発生する可能性があります。
  • 複雑性: システムが複数のレイヤーで構成されるため、設計やデバッグが複雑になることがあります。

2.5 統一インターフェース

特徴:

  • URIで示したリソースに対する操作を、統一したインターフェースで行います

メリット:

  • シンプルさ: 一貫したインターフェースを使用することで、学習のカーブを緩和し、実装のシンプルさを保つことができます。
  • 階層化のしやすさ: システム全体を階層化しやすくなります。

デメリット:

  • 柔軟性の欠如: すべてが同じインターフェースを使用する必要があるため、特定の要件に特化したインターフェースの導入が難しくなる可能性があります。

2.6 コード・オン・デマンド (オプション)

特徴:

  • サーバーからクライアントに実行可能なコードを送信し、クライアント側でそのコードを実行する能力を持ちます。
  • この原則はオプションであり、必須ではありません

メリット:

  • 柔軟性: 必要に応じてクライアントの機能を動的に拡張または変更することができます。
  • 帯域の節約: コードは必要に応じてのみダウンロードされるため、常に全てのコードをクライアントにロードする必要がありません。
  • 最新の機能: サーバー側で更新されたコードをクライアントに提供することで、ユーザーは常に最新の機能や修正を利用できます。

デメリット:

  • セキュリティの懸念: クライアントでのコード実行はセキュリティリスクをもたらす可能性があります。ダウンロードしたコードの信頼性や安全性を確保する必要があります。
  • 互換性: 異なるクライアント環境でのコードの動作を確保するためのテストや検証が必要になる場合があります。
  • パフォーマンス: クライアントで実行するコードのダウンロードや実行に伴う遅延が生じる可能性があります。

3. REST APIとは

REST APIは、ここまで解説した「RESTの原則」に基づいて設計されたWeb APIのことを指します。

REST APIの主な目的は、異なるシステムやアプリケーション間で情報のやり取りを容易にすることにあります。

REST APIは、一般的にHTTPを通信プロトコルとして使用し、リソースを操作するための標準的なHTTPメソッド(GET、POST、PUT、DELETEなど)をサポートしています。

3.1 REST APIの設計レベル

REST APIの設計レベルとは、一般的にLeonard Richardsonが提唱した「Richardsonの成熟度モデル」として知られています。

このモデルは、RESTful APIの「成熟度」や「RESTらしさ」を0から3の4つのレベルで示しています。

レベル 0: シングルURI, シングルHTTPメソッド

  • このレベルのAPIは、ほとんどの操作が単一のURIとHTTPメソッド(たいていはPOST)を使用して実行されるものです。
  • 具体例:古いタイプのSOAPサービスなど。
  • このレベルのAPIはRESTとは言えません。

レベル 1: 複数のURI

  • このレベルでは、異なるリソースに異なるURIが割り当てられます。
  • しかし、まだ全ての操作が同じHTTPメソッド(例えばPOST)を使用しています。
  • 具体例:/users/ordersという2つの異なるURIが存在するが、データの取得や変更のために常にPOSTを使用するサービス。

レベル 2: HTTPメソッドの活用

  • このレベルでは、HTTPメソッド(GET, POST, PUT, DELETEなど)を活用してリソースに対する操作を表現します。
  • これにより、APIの意図がURLだけでなくHTTPメソッドによっても明確にされるようになります。
  • 具体例:ユーザー情報を取得する場合はGET /users/{id}、新しいユーザーを作成する場合はPOST /users、ユーザー情報を更新する場合はPUT /users/{id}など。

レベル 3: HATEOAS (Hypermedia as the Engine of Application State)

  • 最も成熟したレベルです。レスポンスには、リソースの現在の状態だけでなく、次にどのような操作が可能かを示すハイパーメディア(リンクやアクションなど)も含まれます。
  • これにより、クライアントはAPIのドキュメントを頻繁に参照することなく、動的にアクションを決定・実行することができます。
  • 具体例:ユーザー情報の取得レスポンスに、そのユーザーを削除するためのリンクや、関連する注文情報にアクセスするためのリンクが含まれるなど。

このモデルは、APIがどれだけRESTの原則に従っているかを評価するためのガイドラインとして提供されています。

ただし、すべてのAPIがレベル3に到達する必要はありません。使用する状況や要件に応じて、適切なレベルでの設計を選択することが重要です。

4. HTTPメソッドとRESTfulな操作

REST APIの設計では、HTTPメソッドを使用してリソースに対する具体的な操作を指定します。

これにより、APIのエンドポイントが行う動作が明確になります。

4.1 各HTTPメソッドの役割

HTTPメソッド 概要 例示
GET リソースを取得します。 商品一覧を取得: GET /products
POST 新しいリソースを作成します。 新しいユーザー作成: POST /users
PUT 既存のリソースを完全に更新または置き換えます。 ユーザー情報更新: PUT /users/123
DELETE リソースを削除します。 ユーザー削除: DELETE /users/123
HEAD リソースのメタデータのみを取得します。ボディは含まれません。 ヘッダー情報取得: HEAD /products
OPTIONS 対象のリソースでサポートされているHTTPメソッドを知るためのリクエスト。 サポートメソッド確認: OPTIONS /users
PATCH リソースの一部を更新します。 部分的更新: PATCH /users/123

4.2 冪等性と副作用

REST APIの操作の際に、二つの重要な概念として「冪等性」と「副作用」があります。

  • 冪等性 (Idempotency): 同じ操作を何度実行しても、結果が常に同じである性質を指します。例えば、GETやPUT、DELETEは冪等性を持つ操作です。 何度同じリソースに対してこれらのメソッドを実行しても、結果は同じです。 一方、POSTは冪等ではありません。同じデータをPOSTする度に、新しいリソースが作成される可能性があります。
  • 副作用 (Side Effects): 操作がシステムの状態やデータに変更を引き起こす性質を指します。GETは副作用がないとされるのが理想的であり、データやシステムの状態に変更を加えずにデータを取得することが期待されます。 一方、POST, PUT, PATCH, DELETEは明確な副作用を持つ操作です。

5. REST API のリクエス

REST APIのリクエストとは、クライアント(例: ウェブブラウザ、モバイルアプリ、他のサーバーなど)がサーバー上のリソースやデータにアクセス、操作を行うために送信するメッセージのことを指します。

REST APIリクエストは、HTTPプロトコルを基にしており、特定の方法や構造に従ってデータを送信することで、サーバーとのやり取りを実現します。

REST APIのリクエストには以下の要素があります。

1. HTTPメソッド

  • リクエストの種類や目的を示します。
    • 主に使用されるメソッドは
      • GET(データの取得)
      • POST(データの作成)
      • PUT(データの更新)
      • DELETE(データの削除)など。

2. エンドポイントURL

  • アクセスしたいリソースを特定します。例: /users/products/123 など。

3. クエリパラメータ

  • エンドポイントURLに追加することで、特定の情報の絞り込みやページネーションなどの操作を指定します。例: /users?age=25 など

4. ヘッダー情報

  • リクエストに関連するメタ情報や設定を提供します。

5. リクエストボディ

  • POSTPUTなどのメソッドでデータを送信する際に使用される部分で、実際に送信するデータを含みます。
  • 通常、JSONXMLの形式で送信します。

6. 認証情報

  • APIへのアクセスを保護するため、リクエストにはAPIキー、トークン、ユーザー名/パスワードなどの認証情報を含むことが多いです。

6. REST APIのレスポンスとHTTPステータスコード

REST APIのレスポンスとは、クライアントからREST APIへのリクエストを受けた後、サーバーからクライアントに返されるデータや情報のことを指します。

REST APIのレスポンスは、通常、HTTPプロトコルを使用して送信されます。

REST APIのレスポンスには以下の要素があります。

1. ステータスコード

  • リクエストの結果を示す3桁の数字です。

2. ヘッダー情報

  • レスポンスに関するメタ情報を提供します。

3. レスポンスボディ

  • 実際のデータが含まれています。JSONXMLなどが使われます。

4. エラーメッセージ

  • リクエストが失敗した場合や、何らかの問題が発生した場合、エラーメッセージや詳細情報を含めることで、クライアントが問題を診断しやすくなります。

5. リンク情報

  • 特定のRESTful設計のスタイル(例:HATEOAS)では、関連するリソースへのリンクやアクションをレスポンスに含めることが推奨されています。

6.1 ステータスコードの分類

  • 2xx (成功): リクエストが正常に処理された。
  • 4xx (クライアントエラー): クライアント側に問題がある(例: 誤った情報を送信)。
  • 5xx (サーバーエラー): サーバー側に問題がある。

6.2 主なメソッドとステータスコードの組み合わせ

  • GET:
    • 200 OK: リソースが正常に取得された。
    • 404 Not Found: 要求されたリソースが見つからない。
  • POST:
    • 201 Created: 新しいリソースが正常に作成された。
    • 400 Bad Request: リクエストに誤りがあり、リソースが作成されなかった。
  • PUT:
    • 200 OK: リソースが正常に更新された。
    • 201 Created: 新しいリソースが作成された。
    • 400 Bad Request: リクエストに誤りがあり、更新ができなかった。
    • 404 Not Found: 更新対象のリソースが見つからない。
  • PATCH:
    • 200 OK: リソースが部分的に更新された。
    • 400 Bad Request: 更新のリクエストに誤りがある。
    • 404 Not Found: 更新対象のリソースが見つからない。
  • DELETE:
    • 204 No Content: リソースが正常に削除された(応答に内容はない)。200は応答に内容を含んでしまうが、DELETEは基本的に内容はない。
    • 404 Not Found: 削除対象のリソースが見つからない。

参考: