ポリシー作成機能の使用

このトピックでは、ポリシー作成機能を使用してマッシュアップを作成する方法について説明します。ポリシー作成機能は、ポリシーを使用して複数のバックエンド ターゲットからの結果を 1 つのレスポンスに結合する Apigee プロキシ パターンです。

ポリシー作成機能の概要については、API プロキシ クックブック パターンの「ポリシー作成機能パターン」をご覧ください。

サンプルコードをダウンロードして使用する

このクックブック サンプルについて

このクックブック サンプルは、ポリシー作成機能と呼ばれる API プロキシ パターンを示しています。このパターンでは、複数のバックエンド ソースからのデータをマッシュアップする 1 つの方法を提供します(他の方法もあります)。より一般的に言うと、このトピックでは、ポリシーを組み合わせて連結することで目的の結果を生成する方法を説明します。このパターンやその他の関連するパターンの概要については、API プロキシ クックブック パターンをご覧ください。

ここで説明するサンプルでは、ポリシー作成機能を使用して、次の 2 つの別々の公開 API からのデータをマッシュアップします。

  • Google Geocoding API: この API は住所(「東京都港区六本木 6-10-1」など)を地理座標(緯度 35.660428、経度 139.729182 など)に変換します。
  • 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 プロキシを開発できるクラウドベースの開発と対比して示しています。
  • 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 Geocoding サービスに送信されるリクエスト メッセージを作成します。

まず、ポリシーコードを見てみましょう。その後、各要素について詳しく説明します。ダウンロードしたサンプルでは、この 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>
    

このポリシーの要素について以下に簡単に説明します。このポリシーの詳細については、Assign Message ポリシーをご覧ください。

  • <AssignMessage name> - このポリシーの名前を指定します。この名前は、ポリシーをフローで参照するときに使用されます。
  • <AssignTo> - GeocodingRequest という名前付き変数を作成します。この変数は、ServiceCallout ポリシーによってバックエンドに送信されるリクエスト オブジェクトをカプセル化します。
  • <QueryParams> - バックエンド API 呼び出しで必要となるクエリ パラメータを設定します。この場合、Geocoding API は、郵便番号と国 ID で表される場所を把握する必要があります。アプリのユーザーがこの情報を指定します。ここではその情報を抽出します。sensor パラメータはこの API で必須であり、値は 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(countrypostalcode)は不要になったため、ここでは削除します。

次に進む前に: フローの再確認

ここで、別の 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 プロキシの開発で使用される一般的なパターンです。