21世紀においてバックエンドエンジニアがRESTful APIを無視することはほぼ不可能です。なぜなら、RESTful APIは最も人気のあるAPIタイプの一つだからです。その人気の主な理由は、そのスケーラビリティ、柔軟性、そしてシンプルさにあり、これらは現代のAPIで非常に求められている特性です。もしこれらの特性も望ましいなら、RESTfulの原則に従ってAPIを構築することを検討すべきです。この記事では、RESTful APIとみなされるものを説明し、ゼロから設計する方法を実演します。
RESTful APIとは何ですか?
まずはRESTful APIの略称「REST」から始めましょう。「REST」はREpresentational State Transferの略です。これは5つの制約を持つソフトウェアアーキテクチャスタイルです。
- 統一インターフェース
- 無国籍者
- キャッシュ可能
- クライアントとサーバーの分離
- レイヤーシステム。
RESTful APIとは、基本的に上記の制約に違反しないAPIのことです。一つずつ見ていきましょう。
ユニフォームインターフェース
この制約は、API設計に関わるため、バックエンドエンジニアにとって最も関連性の高いものと考えられます。クライアントのデバイスやアプリケーションの種類に関わらず、特定のサーバーと一様にやり取りする方法が一つだけあるべきだと規定しています。以下は、そのような統一インターフェースを構築するためのいくつかのガイドラインです。統一インターフェースは一貫性を確保し、APIの開発と使用を簡素化します。
- リソースベース:クライアントは各リクエストでどのリソース(オブジェクト、データ、またはサービス)にアクセスしようとするかをURI内で指定しなければなりません。
- 表現を通じたリソースの操作:クライアントがリソースを操作(編集または削除)できるようにするために、クライアントはリソースの変更や削除に必要な情報を含むリソースの表現を保持すべきです。
- 自己記述的メッセージ:各メッセージ(リクエストまたはレスポンス)には、受信者がメッセージを理解できる十分な情報が含まれている必要があります。この制約はクライアントとサーバーの両方に適用されます。クライアントはリクエストにHTTPメソッドを含め、リクエストで実行したいアクションをサーバーに示すべきです。サーバーが送信するレスポンスには内容タイプとレスポンスステータスコードが含まれ、クライアントがレスポンスの情報を解釈できるようにすべきです。必要に応じて、クライアントとサーバーはメッセージに他の情報を含めることも可能です。
- アプリケーション状態のエンジンとしてのハイパーメディア(HATEOAS):各応答にはハイパーメディアを含めるべきです。ハイパーメディアは、クライアントが現在の応答を受け取った後にさらにどのようなリクエストを行えるかについての情報です。サーバーはこれを使ってクライアントに次に何ができるかを知らせます。
無国籍者
この制約により、サーバーはクライアントの状態を追跡できません。その結果、クライアントはサーバーの状態追跡に頼ることができず、リクエストを満たすために必要なすべての情報を含める必要があります。サーバーは各リクエストを単独のものとして扱います。このような状態なし状態は、サーバーの状態維持の手間から解放され、可用性が向上します。
キャッシュ可能
この制約により、サーバーはすべての応答で応答がキャッシュ可能かどうか、クライアントがキャッシュできる時間を指定する必要があります。これにより、クライアントとサーバー間の不要な通信を排除し、全体的なパフォーマンスと可用性を向上させる効率的なキャッシュシステムを構築することができます。
クライアントとサーバーの分離
この制約は、RESTful APIアーキテクチャにおけるクライアントとサーバーの役割の分離を示しています。クライアントはリソースの作成、アクセス、操作のリクエストのみを担当します。サーバーはクライアントの要求に応じてリソースの提供と管理のみを担当します。クライアント・サーバー分離により、フロントエンドとバックエンドが独立して進化することが可能になります。
レイヤード・システム
アプリケーションのアーキテクチャにはクライアントとサーバーの間に複数のレイヤーが存在することがあります。これらの中間層は通常、アプリケーションのコア機能と補完的な役割を果たします。例としては、プロキシ(ロードバランシング用)やゲートウェイ(プロトコル変換用)などがあります。「レイヤードシステム」制約は、各レイヤーが隣接するレイヤー以外のレイヤーと相互作用することを制限します。これによりアプリケーションの構造的シンプルさが保証され、レイヤー間の相互作用に不必要な複雑さが加わるのを防ぎます。
RESTful APIの構築方法(例)
次に、具体的な例を用いてRESTful APIの構築方法を示します。前節で述べた制約やガイドラインを参照します。思い出に困った場合は前の節に戻ってください。例えばブログサイトを構築したいとしましょう。第一段階では、以下の動作を実行するためのエンドポイントを開発する必要があります。
- 新しい投稿を作成する
- すべての投稿の取得
- IDによる投稿の取得
- 投稿の更新
- 投稿の削除
必要なURIの数を当てられますか?直感的に言えば、1つの行動には1つのURIが必要だと思われるため、5つに答えたくなる方も多いかもしれません。しかし、「リソースベース」ガイドラインを完全に守れば、2つのURIで十分です。URIはリソースを表すべきで、リソースに対して行われるアクションを表すのではありません。ここで用意しているリソースは、投稿リストと1つの投稿の2種類です。それぞれを表すために、以下の2つのURIを作成できます:
- 投稿一覧:「/api/v1/posts」
- 単一の投稿: '/api/v1/posts/'
こう尋ねたいかもしれません:2つのURIだけで5つの異なるアクションを表現するにはどうすればいいのか?答えは簡単です。HTTPメソッドを使ってアクションを表現でき、同じリソース上で実行されるアクションは同じURIを共有することができます。必要なHTTPメソッドは以下の通りです:
- GET:資源回収
- 投稿:資源の作成
- PUT:資源更新
- 削除:リソースの除去
次に、上記の5つの操作をサポートするエンドポイントの設計方法を見てみましょう。
- 新しい投稿を作成する方法: '[POST] /api/v1/posts'
- すべての投稿の取得:『[GET] /api/v1/posts」
- IDで投稿を取得する方法: '[GET] /api/v1/posts/'
- 投稿の更新: '[PUT] /api/v1/posts/'
- 投稿の削除:「[DELETE] /api/v1/posts/」
次に、各エンドポイントのリクエストとレスポンスがどのような形になるべきかを設計します。それでも、Uniform Interface制約のガイドラインを念頭に置く必要があります。この記事では、第三のアクションに焦点を当てましょう。
IDで投稿を取得する方法: '[GET] /api/v1/posts/'
「Representation によるリソース操作」のガイドラインに従うには、クライアントが特定の投稿を操作(編集または削除)するために必要なすべての情報を持っていることを確実にする必要があります。投稿を編集または削除するには、クライアントが投稿のIDを指定する必要があり、サーバーがどの投稿を操作するかを識別できます。投稿を編集するには、クライアントは編集可能なフィールドと投稿のIDも知る必要があります。クライアントが以下のフィールドを編集できるとしましょう:
- タイトル
- ボディ
すると「[GET] /api/v1/posts/」のレスポンスデータは次のようになるはずです:Response:
{
「id」:1、
"title": RESTful API 101",
「body」:「これはRESTful APIに関する記事です。」
}
クライアントとサーバーが互いに自己記述的メッセージを送り合うことも必要です。「自己記述メッセージ」のガイドラインを念頭に置き、「[GET] /api/v1/posts/」のリクエストとレスポンスを次のように設計できます:リクエスト:
HTTPメソッド:GET
URI: /api/v1/posts/
プロトコル:HTTP/1.1
ヘッダー:Accept: application/json
この要求では、クライアントはHTTPメソッド(GET)を通じてアクションを指定します。クライアントはまた、URI('/api/v1/posts/')を含めてアクションのターゲットリソースを特定しています。さらに、クライアントは使用するプロトコル(HTTP/1.1)と受理するデータの種類(application/json)も含めています。応答:
プロトコル:HTTP/1.1
応答ステータスコード:200 OK
ヘッダー:Content-Type: application/json
{
「id」:1、
"title": RESTful API 101",
「body」:「これはRESTful APIに関する記事です。」
}
この応答では、サーバーは200のレスポンスステータスコードを通じてリクエストが正常に処理されたことをクライアントに通知しています。また、クライアントがレスポンスデータの解釈方法を把握できるようにコンテンツタイプも追加しています。
統一インターフェースを構築するためには、もう一つのガイドラインに従う必要があります。それは「アプリケーション状態のエンジンとしてのハイパーメディア」です。このガイドラインは、サーバーがクライアントが取れるさらなるアクションを含めることを求めています。投稿の詳細を含むレスポンスを受け取った後、クライアントは投稿の編集または削除を選択できます。したがって、サーバーはレスポンスデータに投稿の編集または削除のリクエストを追加できます。レスポンス:
プロトコル:HTTP/1.1
応答ステータスコード:200 OK
ヘッダー:Content-Type: application/json
{
「id」:1、
"title": RESTful API 101",
「body」:「これはRESTful APIに関する記事です。」
「リンク」:[
{
「method」:PUT」、
"uri":"/api/v1/posts/"
},
{
"メソッド":"DELETE",
"uri":"/api/v1/posts/"
}
]
}
統一されたインターフェースを構築したので、システムが「Cacheable」制約に準拠しているか確認しましょう。Cache-Controlヘッダーでこれが可能です。サーバーがクライアントに最大10分(600秒)投稿のキャッシュを許可していると仮定します。その場合、最終的な応答は次のようになります:応答:
プロトコル:HTTP/1.1
応答ステータスコード:200 OK
ヘッダー:
Content-Type: application/json
キャッシュコントロール:最大年齢=600
{
「id」:1、
"title": RESTful API 101",
「body」:「これはRESTful APIに関する記事です。」
「リンク」:[
{
「method」:PUT」、
"uri":"/api/v1/posts/"
},
{
"メソッド":"DELETE",
"uri":"/api/v1/posts/"
}
]
}
「Cache-Control: max-age=600」は、クライアントが最大600秒間データをキャッシュできることを意味します。
これまでに「Uniform Interface」と「Cacheable」制約を説明しました。この例で他の制約を説明するのはシステム設計に関するもので、RESTful APIを構築する際には念頭に置いてください。
概要
この記事では、RESTful APIの定義とRESTful APIが破ってはならない5つの制約について説明しました。また、RESTful APIの構築方法を例とともに示しました。この記事がRESTful APIの理解を深める助けになれば幸いです。
続きを読む:
https://www.geeksforgeeks.org/rest-api-architectural-constraints/ https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design https://restfulapi.net/hateoas/