JavaScript での API プロキシのプログラミング

このトピックでは、JavaScript を使用して HTTP ヘッダーをレスポンス メッセージに動的に追加する方法と、JSON レスポンスを解析し、そのプロパティのサブセットをリクエスト元のアプリに返す方法を説明します。

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

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

このクックブック サンプルは、JavaScript で API の動作を実装する API プロキシ パターンを示しています。JavaScript サンプルは、単純な変数とメッセージ コンテンツの処理方法を示すことを目的としています。1 つのサンプルで変数を取得する方法と設定する方法を示します。JSON を解析して解析結果からメッセージを作成する方法を示す 2 番目のサンプルがあります。

次の 2 つの JavaScript サンプルが API プロキシにあります。

  • setHeaders.js: この JavaScript は、API プロキシの呼び出し時に設定されるいくつかの変数の値を取得します。この JavaScript は、これらの変数をレスポンス メッセージに追加します。こうして、実行するリクエストごとにこれらの値を確認できます。
  • minimize.js: この JavaScript は、メッセージ コンテンツの処理方法を示します。このサンプルを使用する理由は、必要以上のデータがサービスから返されることが多いためです。この JavaScript はレスポンス メッセージを解析して主なプロパティをいくつか抽出し、それらを使ってレスポンス メッセージのコンテンツを作成します。

setHeader.js のコード:

context.setVariable("response.header.X-Apigee-Target", context.getVariable("target.name"));
context.setVariable("response.header.X-Apigee-ApiProxyName", context.getVariable("apiproxy.name"));
context.setVariable("response.header.X-Apigee-ProxyName", context.getVariable("proxy.name"));
context.setVariable("response.header.X-Apigee-ProxyBasePath", context.getVariable("proxy.basepath"));
context.setVariable("response.header.X-Apigee-ProxyPathSuffix", context.getVariable("proxy.pathsuffix"));
context.setVariable("response.header.X-Apigee-ProxyUrl", context.getVariable("proxy.url"));

minimize.js のコード:

//Parse the respose from the target.
var res = JSON.parse(context.proxyResponse.content);

//Pull out only the information we want to see in the response.
var minimizedResponse = { city: res.root.city,
                          state: res.root.state };

//Set the response variable.
context.proxyResponse.content = JSON.stringify(minimizedResponse);

コンテキスト オブジェクトを使用して、JavaScript のフロー変数にアクセスできます。このオブジェクトは、Edge JavaScript オブジェクト モデルに含まれます。オブジェクト モデルの詳細については、JavaScript オブジェクト モデルをご覧ください。

始める前に

このクックブック サンプルを利用する前に、以下の基本的なコンセプトを理解している必要があります。

  • ポリシーの内容と、ポリシーをプロキシにアタッチする方法。ポリシーの概要については、ポリシーとはをご覧ください。
  • プロキシフローの構造。フローの構成をご覧ください。フローを使用すると、API プロキシでポリシーが実行される順序を指定できます。このサンプルでは、さまざまなポリシーを作成して API プロキシフローに追加します。
  • ファイル システムでの API プロキシ プロジェクトの編成方法。API プロキシ構成のリファレンスで説明されています。
  • XML、JSON、JavaScript に関する実務知識。このサンプルでは、ファイル システムにある XML ファイルを使用して API プロキシとそのポリシーを作成します。

サンプルコードをダウンロードすると、このトピックで説明するすべてのファイルが javascript-cookbook サンプル フォルダに含まれています。以降のセクションでは、サンプルコードについて詳しく説明します。

プロキシフローについて

API プロキシで JavaScript を実行するには、「Step」というポリシー アタッチメントを使用してフローにアタッチする必要があります。Javascript(大文字小文字に注意)タイプのポリシーには、単に JavaScript ファイルの名前への参照だけが含まれます。ResourceURL 要素を使用して、ポリシーが JavaScript ファイルを参照するようにします。

たとえば、次のポリシーは setHeader.js という JavaScript ファイルを参照します。

<Javascript name='setHeaders' timeLimit='200'>
    <ResourceURL>setHeaders.js</ResourceURL>
</Javascript>

その他のポリシータイプと同様に、このポリシーを API プロキシフローにアタッチできます。ポリシーを API プロキシフローに添付することで、JavaScript を実行する場所を指定できます。これにより、API プロキシを通過するリクエスト メッセージまたはレスポンス メッセージを操作する JavaScript を実行できます。この例では、両方の JavaScript がレスポンス フローで実行されます。これは、レスポンス メッセージの HTTP ヘッダーの設定と、Apigee Edge からリクエスト元アプリに返されるレスポンス メッセージの「最小化」という 2 つの処理をポリシーで行うためです。

管理 UI でこのフロー構成を開くと、次のようなフロー構成が表示されます。

ナビゲーション パネル[Proxy Endpoints] > [default] > [PostFlow] の順に選択します。

「default」という名前の ProxyEndpoint に対応する XML 構成を以下に示します。

<ProxyEndpoint name="default">
  <PostFlow>
    <Response>
      <!-- Steps reference policies under /apiproxy/policies -->
      <!-- First, set a few HTTP headers with variables for this transaction. -->
      <Step><Name>setHeaders</Name></Step>
      <!-- Next, transform the response from XML to JSON for easier parsing with JavaScript -->
      <Step><Name>transform</Name></Step>
      <!-- Finally, use JavaScript to create minimized response with just city and state. -->
      <Step><Name>minimize</Name></Step>
    </Response>
  </PostFlow>
  <HTTPProxyConnection>
        <!-- BasePath defines the network address for this API proxy. See the script 'invoke.sh' to see how the complete URL for this API proxy is constructed.-->
    <BasePath>/javascript-cookbook</BasePath>
     <!-- Set VirtualHost to 'secure' to have this API proxy listen on HTTPS. -->
    <VirtualHost>default</VirtualHost>
  </HTTPProxyConnection>
  <RouteRule name="default">
    <TargetEndpoint>default</TargetEndpoint>
  </RouteRule>
</ProxyEndpoint>

フローの要素の概要を以下に示します。

  • <Request> - <Request> 要素は、複数の <Step> 要素から構成されます。各ステップは、このトピックの後半で作成するポリシーの 1 つを呼び出します。これらのポリシーは、JavaScript を API プロキシフローにアタッチし、その位置によって JavaScript の実行時点が決まります。
  • <Response> - <Response> 要素にも <Steps> が含まれます。これらのステップでもポリシーを呼び出します。これらのポリシーは、ターゲット エンドポイントからの最終的なレスポンスを処理します。この例では、Apigee の疑似サービス ターゲットがターゲット エンドポイントになります。/apiproxy/targets/default.xml の HTTPTargetConnection の設定に注意してください。
  • <HTTPProxyConnection> - この API を使用するためにアプリから呼び出すネットワーク アドレスを定義する URI パスとホストを指定します。
  • <RouteRule> - この要素には、ProxyEndpoint によって呼び出される TargetEndpoint 構成を指定します。

プロキシへの JavaScript コードの追加

JavaScript(Python スクリプト、Java JAR ファイル、XSLT ファイルなど)はリソースとして保存されます。JavaScript を使用し始めたばかりの時点では、JavaScript ファイルを API プロキシの中に保存するのが最も簡単な方法です。使い続けるにつれて、可能な限り JavaScript を再利用可能で汎用的なものにして、環境レベルまたは組織レベルで保存します。これにより、同じ JavaScript ファイルを多数の API プロキシに保存してやがて管理不能になるのを避けることができます。

組織レベルと環境レベルでのリソースの保存については、リソース ファイルをご覧ください。

演習

プロキシのデプロイと呼び出しの手順については、JavaScript クックブックの README をご覧ください。

API プロキシのインポートとデプロイ

変更が完了したら、管理 UI の API プロキシ ビルダーで API プロキシを保存できます。

または、/api-platform-samples/doc-samples/javascript-cookbook ディレクトリで次のコマンドを実行します。

$ sh deploy.sh

JavaScript のテスト

/api-platform-samples/doc-samples/javascript-cookbook ディレクトリで次のコマンドを実行します。

$ sh invoke.sh

JavaScript により変更されたレスポンス メッセージ内の HTTP ヘッダーを表示するため、シェル スクリプトで curl フラグ -v が使用されています。

リクエストを次のように直接送信できます。

$ curl -v http://{org_name}-test.apigee.net/javascript-cookbook

JavaScript が適切に実行されると、次のようなレスポンスが表示されます。

< X-Apigee-Demo-Target: default
< X-Apigee-Demo-ApiProxyName: simple-javascript
< X-Apigee-Demo-ProxyName: default
< X-Apigee-Demo-ProxyBasePath: /javascript-cookbook
< X-Apigee-Demo-ProxyPathSuffix: /xml
< X-Apigee-Demo-ProxyUrl: http://rrt331ea.us-ea.4.apigee.com/javascript-cookbook/xml

{"city":"San Jose","state":"CA"}

これで、JavaScript を変更して新しい処理を試し、API プロキシを再度デプロイして、同じリクエストの結果を確認できます。変更を反映させるには、JavaScript を含む API プロキシを常に確実にデプロイしてください。

スクリプト エラー

JavaScript の作成時にはエラーの発生を避けることができません。API プロキシにより発行される JavaScript エラーの形式を次に示します。

{
   "fault":{
      "faultstring":"Execution of rewriteTargetUrl failed with error: Javascript runtime error: \"TypeError: Cannot find function getVariable in object TARGET_REQ_FLOW. (rewriteTargetUrl_js#1). at line 1 \"",
      "detail":{
         "errorcode":"steps.javascript.ScriptExecutionFailed"
      }
   }
}

JavaScript を使用するケース

通常、Apigee Edge では、1 つの機能を複数の方法で実装できます。可能であれば、そのまま利用できるポリシーを使用してください。すべての API プロキシ ロジックを JavaScript でコーディングする傾向を避けるのが適切です。Apigee Edge はコンパイル済み JavaScript を使用してパフォーマンス改善を図りますが、JavaScript のパフォーマンスは通常、ポリシーより劣ります。JavaScript の保守とデバッグは難しい場合があります。JavaScript は、独自の要件を満たす固有の機能にのみ使用してください。

カスタム機能のパフォーマンスを懸念している場合は、可能であれば Java を利用してください。

まとめ

このクックブック トピックでは、JavaScript を API プロキシ構成に組み込み、カスタム動作を実装する方法を説明しました。サンプルで実装されるカスタム動作は、変数を取得する方法と、JSON を解析してカスタム レスポンス メッセージを作成する方法を示しています。