RESTful APIの理解と活用
Yi Sun
December 2, 2022
インターネット・オブ・エブリシング(IoE)の時代において、さまざまなAPIが存在し、それらを標準化することが重要です。RESTful APIは、最も人気のあるAPIアーキテクチャスタイルの一つであり、クライアント側とサーバー側の関心事を分離し、フロントエンドとバックエンドを別々に反復できるようにすることで効率を向上させます。そのステートレスな特性により、アプリケーションの拡張性が高まり、キャッシュポリシーを容易に実装できるため、ユーザーエクスペリエンスとパフォーマンスが向上します。 この記事では、RESTful APIとは何か、そしてそれをどのように使用できるかを紹介します。
APIとは何か
APIが何であるかを一旦置いておき、私たちが日常生活でどのように情報を伝達しているかについて考えてみましょう。
あなたが店で店主にお金を渡し、電池を買いたいと伝えると、店主はお金を受け取り、棚から電池を見つけてあなたに手渡します。これで電池を購入する取引が成功しました。
一方、コンピュータソフトウェアは、APIを通じてこれを実現します。まずはWikipediaの定義から見てみましょう:
アプリケーションプログラミングインターフェース(API)は、2つ以上のコンピュータプログラムが互いに通信するための方法です。これはソフトウェアインターフェースの一種であり、他のソフトウェアに対してサービスを提供します。
ソフトウェアAがAPIを通じてソフトウェアBにリクエストを送り、ソフトウェアBはそのリソースを検索した後、APIを通じてAにレスポンスを返します。
ソフトウェアAがAPIを通じてソフトウェアBにリクエストを送ることは、あなたが店主に電池が必要だと伝えることに似ています。そして、ソフトウェアBがデータをソフトウェアAに返すことは、店主が電池を見つけてあなたに渡すことに似ています。
このプロセスでは、ソフトウェアBがソフトウェアAがデータを必要とする理由を知る必要はありません。ちょうど店主があなたに電池を買う理由を尋ねないのと同じです。ソフトウェアAも、ソフトウェアBがどのようにデータを見つけたかを知る必要はありません。あなたが電池を買うときに、店主に電池がどこで購入されたかを尋ねないのと同じです。各ソフトウェアはAPIを通じて情報をやり取りし、それぞれが自分の役割を果たすことで、プログラミングの世界は秩序正しく信頼性が高くなります。
RESTful APIとは何か
Roy Fieldingは、2000年の博士論文「Architectural Styles and Web-Based Software Architecture Design」でREST(Representational State Transfer)を定義し、RESTアーキテクチャスタイルは6つのガイドラインを定義しています。これらの制約の一部またはすべてに準拠するシステムは、広くRESTfulと呼ばれます。
(出典: Seobility)
RESTful APIの制約
制約 | 詳細 | 利点 |
---|---|---|
クライアント-サーバーアーキテクチャ | ユーザーインターフェースの問題とデータストレージの問題を分離することで、複数のプラットフォームでのユーザーインターフェースの移植性を向上させ、サーバーコンポーネントを簡素化することで拡張性を向上させます。 | 1. クライアント側とサーバー側の分離。 2. ユーザープラットフォームのクロスプラットフォーム移植性を向上。 3. サーバー側の拡張性を向上。 |
ステートレス性 | クライアントからサーバーへの各リクエストには、リクエストに必要なすべての情報が含まれている必要があり、サーバーに保存されているコンテキストを利用してはならず、セッション状態は完全にクライアント側に保存されます。 | 1. 拡張が容易で、セッションの依存関係がなく、どのサーバーも任意のリクエストを処理できます。 2. キャッシュが容易で、プログラムのパフォーマンスが向上します。 |
キャッシュ可能性 | リクエストまたはレスポンス内のデータが暗黙的または明示的にキャッシュ可能または非キャッシュ可能としてマークされている必要があります。レスポンスがキャッシュ可能であれば、クライアントキャッシュはそのレスポンスデータを後続の同等のリクエストに再利用する権利を与えられます。 | 1. 帯域幅を削減。 2. レイテンシを削減。 3. サーバーの負荷を削減。 4. ネットワークの状態を隠蔽。 |
階層化システム | コンポーネントの動作を制約することで、アーキテクチャを階層化し、各コンポーネントが相互作用する直近の階層を超えて「見る」ことができないようにします。システムの知識を単一の階層に制限することで、システム全体の複雑さが減少し、基盤の独立性が促進されます。 | 1. システム全体の複雑さを削減。 2. 基盤の独立性を促進。 3. ロードバランシングを容易に実装。 4. ビジネスロジックとセキュリティポリシーを分離。 |
コードオンデマンド(オプション) | クライアントの機能を拡張するために、アプレットやスクリプトの形でコードをダウンロードして実行できるようにします。 | 1. システムの拡張性を向上。 |
統一インターフェース | 4つの主要なポイントを含みます: 1. リクエスト内のリソース識別。 クライアントはリクエストに含まれるURIによってリソースを識別でき、サーバー側のリソースとクライアントがリクエストしたリソースを分離します。 2. リソース操作を表現を通じて行う。 クライアントがリソースの表現(URIなど)を持っている場合、リソースを変更または削除するのに十分な情報があります。 3. 自己記述型メッセージ。 すべてのメッセージには、クライアントがメッセージをどう処理するかを知るのに十分な情報が含まれています。 4. アプリケーション状態のエンジンとしてのハイパーメディア(HATEOAS)。 クライアントは、サーバーが返すリソースリンクを通じてユーザーにすべてのリソースを提供するために追加のコーディングを必要としません。 | 1. システム全体のアーキテクチャを簡素化。 2. 相互作用の可視性を向上。 |
RESTful APIのベストプラクティス
コンポーネント間の統一インターフェースに重点を置くことは、RESTアーキテクチャスタイルを他のウェブベースのスタイルと区別するコア機能です。この機能に基づいて、APIをより良く設計するためのベストプラクティスを整理しました。
パス名に動詞を使用しない
リソース操作の動作を表現するためにHTTPメソッドを使用し、動作動詞をパスに定義しないようにします。
// Good
curl -X GET http://httpbin.org/orders
// Bad
curl -X GET "http://httpbin.org/getOrders"
- GETを使用して指定されたURIのリソース情報を取得
// 現在のシステムのすべての注文情報を取得することを表します
curl -X GET http://httpbin.org/orders
// 注文番号1の注文詳細情報を取得することを表します
curl -X GET http://httpbin.org/orders/1
- POSTを使用して指定されたURIにリソースを作成
// 名前がorderのリソースを作成することを表します
curl -X POST http://httpbin.org/orders \
-d '{"name": "awesome", region: "A"}' \
- PUTを使用して指定されたURIにリソースを作成または完全に置換
// idが1の注文のデータを置換することを表します
curl -X PUT http://httpbin.org/orders/1 \
-d '{"name": "new awesome", region: "B"}' \
- PATCHを使用してリソースの部分的な更新を実行
// idが1の注文のregionフィールドを変更し、残りのデータは変更しないことを表します
curl -X PATCH http://httpbin.org/orders/1 \
-d '{region: "B"}' \
- DELETEを使用して指定されたURIのリソースを削除
// idが1の注文を削除することを表します
curl -X DELETE http://httpbin.org/orders/1
URIは複数形を使用
特定の種類のリソースにアクセスするために単数形を使用したい場合:
curl -X GET "http://httpbin.org/order"
単数形を使用すると、システム内に注文が1つしかないとユーザーが誤解する可能性がありますが、複数形を使用すると理解がスムーズになります。
curl -X GET "http://httpbin.org/orders"
HTTPステータスコードを適切に使用
HTTP標準ではステータスコードが定義されており、以下のように大別できます:
ステータスコード | 意味 |
---|---|
2xx | 成功、操作が正常に受信され処理されました |
3xx | リダイレクト、リクエストを完了するためにさらなるアクションが必要です |
4xx | クライアントエラー、リクエストに構文エラーが含まれているか、リクエストを完了できませんでした |
5xx | サーバーエラー、サーバーがリクエストを処理中にエラーが発生しました |
標準的なステータスコードを使用することで、開発者はすぐに問題を特定し、さまざまな種類のエラーを見つける時間を短縮できます。
バージョン管理
ビジネス要件の変化に伴い、すでにオンラインになっているAPIはそれに応じて調整する必要があります。もしAPIが第三者によって使用されている場合、すべてのクライアントがAPIの変更に合わせて変更することは明らかに不可能です。そのため、APIバージョン管理の概念を導入する必要があります。これにより、過去のAPIの正常な使用を保証し、新しいAPIを反復して新しいビジネス要件を満たすことができます。
一般的なバージョン管理の手段は以下の通りです:
- リクエストのパスによるバージョン管理
// v1 APIをリクエスト
curl http://httpbin.org/v1/orders
// v2 APIをリクエスト
curl http://httpbin.org/v2/orders
- クエリパラメータによるバージョン管理
// v1 APIをリクエスト
curl http://httpbin.org/orders?version=v1
// v2 APIをリクエスト
curl http://httpbin.org/v2/orders?version=v2
- ヘッダーによるバージョン管理
// v1 APIをリクエスト
curl http://httpbin.org/orders -H "custom-version: v1"
// v2 APIをリクエスト
curl http://httpbin.org/orders -H "custom-version: v2"
APISIXがRESTful APIを強化する方法
Apache APISIXは、動的でリアルタイム、高性能なAPIゲートウェイです。これは任意のRESTful APIサービスの前に配置され、プラグインを使用して新しいサービスを追加し、その機能を拡張できます。これはRESTfulの階層化システムの定義に合致します。さらに、RESTful API定義に従っていない一部の歴史的なサービスについても、APISIXは元のビジネスコードを変更せずにインターフェースを変換し、インターフェースが統一インターフェースのREST制約を満たすようにすることで、APIがRESTful API仕様に準拠するよう支援します。
階層化システム:ビジネスロジックとセキュリティロジックの分離をサポート
ビジネスロジックの実装に集中し、インターフェースのセキュリティロジックはAPISIXの認証クラスのプラグイン(例:key-auth)に任せることができます。APISIXは多数の認証プラグインをサポートしており、openid-connectを例にとると、以下の図のようになります:
APISIX(APIゲートウェイ)を使用して、ビジネスサーバーの前に認証ロジックの層を追加することで、上流サービスを保護することができます。このアーキテクチャパターンは、ビジネスロジックとセキュリティロジックを分離するのに役立ちます。
階層化システム:複数のロードバランシングプロトコルをサポート
APISIXはAPIゲートウェイとして、クライアントとサーバー側の間に配置され、さまざまなロード要件を満たすことができます。ロードバランシングロジックをカスタマイズすることも可能です。
サポートされているロードバランシングアルゴリズムは以下の通りです:
roundrobin
: 重み付きラウンドロビンバランシング。chash
: 一貫性のあるハッシュ。ewma
: 最小レイテンシのノードを選択。詳細はEWMA Chartを参照。least_conn
:(active_conn + 1) / weight
の値が最小のノードを選択。ここで、active_connはリクエストによって使用されている接続であり、Nginxの概念と似ています。require("apisix.balancer.your_balancer")
を通じてロードされるユーザー定義のロードバランサー
統一インターフェース:歴史的なAPIをよりRESTfulに
長い間存在し、RESTful APIガイドラインに従っていない歴史的なAPIについては、APISIXを通じて新しいAPIを再カプセル化し、元のAPIロジックを変更せずに異なるビジネスシナリオに対応できます。
- proxy-rewriteを使用してクライアントリクエストを書き換える
前述のように、パスに動詞を含めるべきではありません。
例えば、歴史的なAPIに/getOrder
インターフェースがある場合、proxy-rewriteプラグインを使用してAPIリクエストを歴史的なAPIにプロキシできます。
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"methods": ["GET"],
"uri": "/orders",
"plugins": {
"proxy-rewrite": {
"uri": "/getOrder",
"scheme": "http",
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:80": 1
}
}
}'
また、APIのバージョン管理操作にもこのプラグインを使用できます。
- response-rewriteプラグインを使用してサーバー側のレスポンスを書き換える
歴史的なAPIに標準化されていないレスポンスステータスコードがある場合、response-rewriteを使用してレスポンスをプロキシし、レスポンスステータスコードを変更できます。
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"methods": ["GET"],
"uri": "/orders",
"plugins": {
"response-rewrite": {
"status_code": 201,
"body": "{\"code\":\"ok\",\"message\":\"new json body\"}",
"vars":[
[ "status","==",200 ]
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:80": 1
}
}
}'
上記の例は、/orders
パスをリクエストするAPIのステータス200を201に変更するリクエストを表します。
APISIXは非常に豊富なプラグインをサポートしているため、さらに多くの使い方を探求することを楽しみにしています。
まとめ
この記事では、APIとは何か、RESTful APIとは何か、そしてそのベストプラクティスを紹介しました。さらに、APISIXを使用してビジネスロジックとセキュリティロジックを分離する方法、および元のビジネスコードを変更せずに歴史的なAPIサービスをよりRESTfulにする方法についても紹介しました。この記事がRESTful APIを理解するのに役立つことを願っています。