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 でこのフロー構成を開くと、次のようなフロー構成が表示されます。

[Navigator] ペイン[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> - この要素は、どの TargetEndpoint 構成が ProxyEndpoint で呼び出されるかを指定します。

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

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

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

演習

プロキシのデプロイと呼び出しの手順については、JavaScript cookbook 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 を解析してカスタム レスポンス メッセージを作成する方法を示しています。