このトピックでは、ポリシー作成機能を使用してマッシュアップを作成する方法について説明します。ポリシー作成機能は、ポリシーを使用して複数のバックエンド ターゲットからの結果を 1 つのレスポンスに結合する Apigee プロキシ パターンです。
ポリシー作成の概要については、API プロキシ クックブック パターンで「ポリシー作成パターン」をご覧ください。
サンプルコードをダウンロードして使用する
このクックブック サンプルについて
このクックブック サンプルでは、ポリシー作成という API プロキシ パターンについて説明します。このパターンでは、複数のバックエンド ソースからのデータをマッシュアップする 1 つの方法を提供します(他の方法もあります)。より一般的に言うと、このトピックでは、ポリシーを組み合わせて連結することで目的の結果を生成する方法を説明します。このパターンの概要とその他の関連するパターンについては、API プロキシ クックブック パターンをご覧ください。
ここで説明するサンプルでは、ポリシー作成機能を使用して、次の 2 つの別々の公開 API からのデータをマッシュアップします。
- Google Geocoding API: この API は、住所(1600 Amphitheatre Parkway, Mountain View, CA など)を地理座標(緯度: 37.423021、経度: 122.083739 など)に変換します。
- Google Elevation API: この API は、地球上の場所の標高データをクエリで取得するためのシンプルなインターフェースを提供します。このサンプルでは、Geocoding API から返された座標がこの API への入力として使用されます。
アプリのデベロッパーは、郵便番号と国 ID の 2 つのクエリ パラメータを指定して、この API プロキシを呼び出します。
$ curl "http://{myorg}-test.apigee.net/policy-mashup-cookbook?country=us&postalcode=08008"
レスポンスは、指定された郵便番号地域の中心のジオコード化された場所(緯度 / 経度)とそのジオコード化された場所の標高との組み合わせを含む JSON オブジェクトです。
{ "ElevationResponse":{ "status":"OK", "result":{ "location":{ "lat":"39.7500713", "lng":"-74.1357407" }, "elevation":"0.5045232", "resolution":"76.3516159" } } }
始める前に
ポリシー作成パターンの概要については、API プロキシ クックブック パターンで「ポリシー作成パターン」をご覧ください。
このクックブック サンプルを利用する前に、以下の基本的なコンセプトを理解している必要があります。
- ポリシーの内容と、ポリシーをプロキシにアタッチする方法。ポリシーの概要については、ポリシーとはをご覧ください。
- API プロキシフローの構造。フローの構成をご覧ください。フローにより、API プロキシが複数のポリシーを実行する順序を指定できます。このサンプルでは、複数のポリシーを作成して API プロキシのフローに追加します。
- ファイル システムでの API プロキシ プロジェクトの編成方法。API プロキシ構成のリファレンスで説明されています。このクックブックのトピックでは、ローカル開発(ファイル システムベース)と、管理 UI を使用して API プロキシを開発できるクラウドベースの開発を対比して示しています。
- API キー検証の使用。これは、API に構成できるアプリベースのセキュリティの中で最も簡単な方法です。詳細については、API キーをご覧ください。API キーの要求による API の保護チュートリアルもご覧ください。
- XML の実務知識。このサンプルでは、ファイル システムにある XML ファイルを使用して API プロキシとそのポリシーを作成します。
サンプルコードをダウンロードすると、このトピックで説明するすべてのファイルが mashup-policy-cookbook サンプル フォルダに含まれています。以降のセクションでは、サンプルコードについて詳しく説明します。
フローの概要
ポリシーの説明に移る前に、サンプル API プロキシのメインフローを見てみましょう。以下に示すフロー XML は、このプロキシの詳細、プロキシで使用されるポリシー、それらのポリシーがどこで呼び出されるかを示しています。
ダウンロードしたサンプルで、この XML は doc-samples/policy-mashup-cookbook/apiproxy/proxies/default.xml
ファイルに含まれています。
<ProxyEndpoint name="default"> <Flows> <Flow name="default"> <Request> <!-- Generate request message for the Google Geocoding API --> <Step><Name>GenerateGeocodingRequest</Name></Step> <!-- Call the Google Geocoding API --> <Step><Name>ExecuteGeocodingRequest</Name></Step> <!-- Parse the response and set variables --> <Step><Name>ParseGeocodingResponse</Name></Step> <!-- Generate request message for the Google Elevation API --> <Step><Name>AssignElevationParameters</Name></Step> </Request> <Response> <!-- Parse the response message from the Elevation API --> <Step><Name>ParseElevationResponse</Name></Step> <!-- Generate the final JSON-formatted response with JavaScript --> <Step><Name>GenerateResponse</Name></Step> </Response> </Flow> </Flows> <HTTPProxyConnection> <!-- Add a base path to the ProxyEndpoint for URI pattern matching--> <BasePath>/policy-mashup-cookbook</BasePath> <!-- Listen on both HTTP and HTTPS endpoints --> <VirtualHost>default</VirtualHost> <VirtualHost>secure</VirtualHost> </HTTPProxyConnection> <RouteRule name="default"> <!-- Connect ProxyEndpoint to named TargetEndpoint under /targets --> <TargetEndpoint>default</TargetEndpoint> </RouteRule> </ProxyEndpoint>
フローの要素の概要を以下に示します。
- <Request> - <Request> 要素は、複数の <Step> 要素から構成されます。各ステップは、このトピックの後半で作成するポリシーのうち 1 つを呼び出します。これらのポリシーは、リクエスト メッセージの作成とその送信、レスポンスの解析に関連しています。このトピックが終わる頃には、これらの各ポリシーのロールがわかるようになります。
- <Response> - <Response> 要素にも <Steps> が含まれています。これらのステップでもポリシーを呼び出します。これらのポリシーは、ターゲット エンドポイント(Google Elevation API)からの最終的なレスポンスを処理します。
- <HttpProxyConnection> - この要素では、アプリをこの API プロキシに接続する方法の詳細を指定します。ここには、この API の呼び出し方法を指定する <BasePath> が含まれます。
- <RouteRule> - この要素には、インバウンド リクエスト メッセージが処理された直後の動作を指定します。この場合は、TargetEndpoint が呼び出されます。この重要なステップについては、このトピックで後ほど詳しく説明します。
ポリシーの作成
以降の各セクションでは、このポリシー作成機能のサンプルを構成する各ポリシーについて説明します。
最初の AssignMessage ポリシーを作成する
以下に示す最初の AssignMessage ポリシーは、Google ジオコーディング サービスに送信されるリクエスト メッセージを作成します。
まず、ポリシーコードを見てみましょう。その後、各要素について詳しく説明します。サンプルをダウンロードすると、この XML は doc-samples/policy-mashup-cookbook/apiproxy/policies/GenerateGeocodingRequest.xml
ファイルにあります。
<AssignMessage name="GenerateGeocodingRequest"> <AssignTo createNew="true" type="request">GeocodingRequest</AssignTo> <Set> <QueryParams> <QueryParam name="address">{request.queryparam.postalcode}</QueryParam> <QueryParam name="region">{request.queryparam.country}</QueryParam> <QueryParam name="sensor">false</QueryParam> </QueryParams> <Verb>GET</Verb> </Set> <!-- Set variables for use in the final response --> <AssignVariable> <Name>PostalCode</Name> <Ref>request.queryparam.postalcode</Ref> </AssignVariable> <AssignVariable> <Name>Country</Name> <Ref>request.queryparam.country</Ref> </AssignVariable> </AssignMessage>
このポリシーの要素について以下に簡単に説明します。このポリシーの詳細については、Message ポリシーの割り当てをご覧ください。
- <AssignMessage name> - このポリシーに名前を付けます。この名前は、ポリシーをフローで参照するときに使用されます。
- <AssignTo> - GeocodingRequest という名前の変数を作成します。この変数は、ServiceCallout ポリシーによってバックエンドに送信されるリクエスト オブジェクトをカプセル化します。
- <QueryParams> - バックエンド API 呼び出しに必要なクエリ パラメータを設定します。この場合、Geocoding API は、郵便番号と国 ID で表される場所を把握する必要があります。アプリのユーザーがこの情報を指定します。ここではその情報を抽出します。この API で
sensor
は必須で、値は true または false です。ここでは、false にハードコードします。 - <Verb> - この場合、API に対して単純な GET リクエストを行います。
- <AssignVariable> - これらの変数は、API に渡される値を格納します。この例では、クライアントに返されたレスポンスでこれらの変数にアクセスします。
ServiceCallout でリクエストを送信する
ポリシー作成機能の次のステップでは、ServiceCallout ポリシーを作成します。次に示す ServiceCallout ポリシーは、前の AssignMessage ポリシーで作成したリクエスト オブジェクトを Google Geocoding サービスに送信し、GeocodingResponse という変数に結果を保存します。
先ほどと同じように、まずコードを見てみましょう。その後、詳しく説明します。このポリシーの詳細については、Service Callout ポリシーをご覧ください。ダウンロードしたサンプルで、この XML は doc-samples/policy-mashup-cookbook/apiproxy/policies/ExecuteGeocodingRequest.xml
ファイルに含まれています。
<ServiceCallout name="ExecuteGeocodingRequest"> <Request variable="GeocodingRequest"/> <Response>GeocodingResponse</Response> <HTTPTargetConnection> <URL>http://maps.googleapis.com/maps/api/geocode/json</URL> </HTTPTargetConnection> </ServiceCallout>
このポリシーの要素について以下に簡単に説明します。
- <ServiceCallout> - 前のポリシーと同様に、このポリシーにも名前があります。
- <Request variable> - AssignMessage ポリシーで作成された変数です。これは、バックエンド API に送信されるリクエストをカプセル化します。
- <Response> - この要素では、レスポンスを格納する変数の名前を指定します。この変数には、ExtractVariables ポリシーで後ほどアクセスします。
- <HTTPTargetConnection> - バックエンド API のターゲット URL を指定します。この場合、API が JSON レスポンスを返すように指定します。
これで、2 つのポリシーが作成されました。1 つは、バックエンド API(Google の Geocoding API)を使用するために必要なリクエスト情報を指定するものです。2 つ目は、実際にリクエストをバックエンド API に送信するものです。次は、レスポンスを処理します。
ExtractVariables でレスポンスを解析する
ExtractVariables ポリシーでは、ServiceCallout ポリシーで取得したレスポンス メッセージの内容を簡単に解析できます。ExtractVariables を使用して JSON や XML を解析することも、URI パス、HTTP ヘッダー、クエリ パラメータ、フォーム パラメータから内容を抽出することもできます。
ExtractVariables ポリシーのリストを以下に示します。ポリシーの詳細については、Extract Variables ポリシーをご覧ください。ダウンロードしたサンプルで、この XML は doc-samples/policy-mashup-cookbook/apiproxy/policies/ParseGeocodingResponse.xml
ファイルに含まれています。
<ExtractVariables name="ParseGeocodingResponse"> <Source>GeocodingResponse</Source> <VariablePrefix>geocoderesponse</VariablePrefix> <JSONPayload> <Variable name="latitude"> <JSONPath>$.results[0].geometry.location.lat</JSONPath> </Variable> <Variable name="longitude"> <JSONPath>$.results[0].geometry.location.lng</JSONPath> </Variable> </JSONPayload> </ExtractVariables>
ExtractVariable ポリシーの主な要素は次のとおりです。
- <ExtractVariables name> - この場合も、ポリシーをフローで使用するときにポリシーを参照するために使用されます。
- <Source> - ServiceCallout ポリシーで作成したレスポンス変数を指定します。このポリシーは、この変数からデータを抽出します。
- <VariablePrefix> - 変数接頭辞では、このポリシーで作成される他の変数の名前空間を指定します。この接頭辞には、Edge の事前定義変数で定義されている予約済みの名前を除き、任意の名前を使用できます。
- <JSONPayload> - この要素は、目的のレスポンス データを取得し、名前付き変数に格納します。実際には、Geocoding API は、緯度と経度以外にもさまざまな情報を返します。ただし、このサンプルで必要な値は緯度と経度のみです。Geocoding API から返される JSON の完全なレンダリングについては、API のドキュメントをご覧ください。geometry.location.lat と geometry.location.lng の値は、返される JSON オブジェクト内の多数の項目のうちの 2 つにすぎません。
明らかでない場合もありますが、このポリシーで指定した変数接頭辞(geocoderesponse)と実際の変数名で名前が構成される 2 つの変数が ExtractVariables によって生成されることを確認することが重要です。これらの変数は API プロキシに格納され、プロキシフロー内の他のポリシーで使用できるようになります。これらの変数は次のとおりです。
- geocoderesponse.latitude
- geocoderesponse.longitude
以上で、ほとんどの作業が終わりました。リクエストの作成、バックエンド API の呼び出し、返された JSON データの解析を行う 3 つのポリシーの複合体を作成しました。最後のステップでは、フローのこの部分から別の AssignMessage ポリシーにデータを渡し、2 つ目のバックエンド API(Google Elevation API)を呼び出して、マッシュアップされたデータをアプリ デベロッパーに返します。
AssignMessage で 2 つ目のリクエストを生成する
次に示す AssignMessage ポリシーでは、最初のバックエンド(Google Geocoding)から返されて保存した変数を使用し、2 つ目の API(Google Elevation)に送信するリクエストにそれらを投入します。前述したように、これらの変数は geocoderesponse.latitude と geocoderesponse.longitude です。
ダウンロードしたサンプルで、この XML は doc-samples/policy-mashup-cookbook/apiproxy/policies/AssignElevationParameters.xml
ファイルに含まれています。
<AssignMessage name="AssignElevationParameters"> <Remove> <QueryParams> <QueryParam name="country"/> <QueryParam name="postalcode"/> </QueryParams> </Remove> <Set> <QueryParams> <QueryParam name="locations">{geocoderesponse.latitude},{geocoderesponse.longitude}</QueryParam> <QueryParam name="sensor">false</QueryParam> </QueryParams> </Set> </AssignMessage>
Google Elevation API を調べると、2 つのクエリ パラメータを受け取ることがわかります。1 つ目のパラメータは locations
で、その値は緯度と経度(カンマ区切り値)です。もう一方のパラメータは sensor
です。このパラメータは必須で、値は true または false である必要があります。この時点で最も重要なのは、ここで作成するリクエスト メッセージには ServiceCallout が必要でないということです。プロキシの TargetEndpoint からバックエンド API を呼び出すことができるため、この時点で ServiceCallout から 2 つ目の API を呼び出す必要はありません。Google Elevations API を呼び出すために必要なデータはすべてそろっています。このステップで生成されるリクエスト メッセージは、メインのリクエスト パイプラインについて生成されるリクエストとは異なり ServiceCallout を必要としないため、ProxyEndpoint によって TargetEndpoint に転送された後、この API プロキシについて構成された RouteRule に転送されます。TargetEndpoint は、リモート API との接続を管理します。Elevation API の URL は、TargetEndpoint の HTTPConnection で定義します。詳細については、Elevation API のドキュメントをご覧ください。前に保存した QueryParams(country
と postalcode
)は不要になったため、ここでは削除します。
次に進む前に: フローの再確認
ここで、別の ServiceCallout ポリシーを作成しない理由を考えてみましょう。最終的には、別のメッセージを作成しました。そのメッセージは、ターゲットである Google Elevation API にどのようにして送信されるのでしょうか。これは、フローの <RouteRule> 要素で送信されます。<RouteRule> では、フローの <Request> 部分が実行された後の残りのリクエスト メッセージの処理方法を指定します。この <RouteRule> で指定した TargetEndpoint によって、API プロキシはメッセージを http://maps.googleapis.com/maps/api/elevation/xml
に送信するよう指示されます。
ダウンロードしたサンプル API プロキシの場合、TargetProxy XML は doc-samples/policy-mashup-cookbook/apiproxy/targets/default.xml
ファイルにあります。
<TargetEndpoint name="default"> <HTTPTargetConnection> <!-- This is where we define the target. For this sample we just use a simple URL. --> <URL>http://maps.googleapis.com/maps/api/elevation/xml</URL> </HTTPTargetConnection> </TargetEndpoint>
次は、Google Elevation API からのレスポンスを処理する必要があります。それが終われば完了です。
レスポンスを XML から JSON に変換する
このサンプルでは、Google Elevation API からのレスポンスが XML として返されます。追加演習として、複合体にポリシーをもう 1 つ追加して、レスポンスを XML から JSON に変換しましょう。
このサンプルでは、変換を行うために、GenerateResponse という名前の JavaScript ポリシーと JavaScript コードを含むリソース ファイルを使用します。GenerateResponse ポリシーの定義を次に示します。
<Javascript name="GenerateResponse" timeout="10000"> <ResourceURL>jsc://GenerateResponse.js</ResourceURL> </Javascript>
GenerateResponse.js リソース ファイルには、変換を行うために使用される JavaScript が含まれています。このコードは doc-samples/policy-mashup-cookbook/apiproxy/resources/JSC/GenerateResponse.js
ファイルで確認できます。
Apigee では、XML を JSON に変換するためにすぐに使用できる XMLToJSON ポリシーも提供しています。ProxyEndpoint を編集して、次に示す xmltojson
ポリシーを代わりに使用することもできます。
<XMLToJSON name="xmltojson"> <Options> </Options> <OutputVariable>response</OutputVariable> <Source>response</Source> </XMLToJSON>
サンプルのテスト
まだ行っていない場合は、policy-mashup-cookbook サンプルをダウンロードしてデプロイし、実行してみてください。このサンプルは、GitHub の Apigee Edge サンプル リポジトリの doc-samples フォルダにあります。policy-mashup-cookbook フォルダにある README ファイルの指示に従ってください。または、サンプル API プロキシの使用の手順の概要に従ってください。
要約すると、複合 API は次のように呼び出すことができます。{myorg} は自分の組織名に置き換えます。
$ curl "http://{myorg}-test.apigee.net/policy-mashup-cookbook?country=us&postalcode=08008"
レスポンスには、アプリのエンドユーザーによって指定された郵便番号地域の中心のジオコード化された場所とそのジオコード化された場所の標高との組み合わせが含まれます。このデータは 2 つのバックエンド API から取得され、API プロキシに添付されたポリシーによってマッシュアップされて、1 つのレスポンスでクライアントに返されたものです。
{ "country":"us", "postalcode":"08008", "elevation":{ "meters":0.5045232, "feet":1.6552599030345978 }, "location":{ "latitude":39.75007129999999, "longitude":-74.1357407 } }
まとめ
このクックブックのトピックでは、ポリシー作成機能パターンを使用して、複数のバックエンド ソースからのデータのマッシュアップを作成する方法を説明しました。ポリシー作成機能は、API にクリエイティブな機能を追加するために API プロキシの開発で使用される一般的なパターンです。