JavaScript ポリシー

概要

このポリシーを使用すると、API プロキシフローの処理中にカスタム JavaScript コードを実行できます。カスタム JavaScript コードでは、Apigee Edge JavaScript オブジェクト モデルのオブジェクト、メソッド、プロパティを使用できます。このオブジェクト モデルを使用すると、プロキシフローの処理中に変数を取得、設定、削除できます。オブジェクト モデルで提供される基本的な暗号機能を使用することもできます。

特徴

JavaScript ポリシーには数多くのユースケースがあります。たとえば、フロー変数の取得と設定、カスタム ロジックの実行と障害処理の実施、リクエストやレスポンスからのデータの抽出、バックエンド ターゲット URL の動的編集などがあります。このポリシーを使用すると、標準 Edge ポリシーでカバーされていないカスタム動作を実装できます。実際に、JavaScript ポリシーを使用して、AssignMessage や ExtractVariable などの他のポリシーにより実装されるのと同じ動作を数多く実現できます。

JavaScript ポリシーでのロギングはおすすめできません。Message Logging ポリシーの方が、Splunk、Sumo、Loggly などのサードパーティ製ロギング プラットフォームへのロギングに非常に適しています。また、Message Logging ポリシーを、レスポンスがクライアントに返信された後で実行する PostClientFlow で実行することで、API プロキシのパフォーマンスを向上させることができます。

基本的に、JavaScript ポリシーは、実行する JavaScript ソースファイルの名前を、ポリシーが添付されているステップを実行するときに指定します。ソースファイルは、常にプロキシ バンドル内の標準の場所: apiproxy/resources/jsc に格納されます。あるいは、ソースコードを環境レベルあるいは組織レベルのリソース ファイルに格納することもできます。手順については、リソース ファイルをご覧ください。管理 UI プロキシ エディタを介して JavaScript をアップロードすることもできます。

JavaScript ソースファイルは必ず拡張子を .js にしてください。

現在サポートされている JavaScript のバージョンについては、サポート対象ソフトウェアとサポート対象バージョンをご覧ください。

動画

JavaScript ポリシーを使用してカスタム ポリシー拡張機能を作成する方法についての動画をご覧ください。

サンプル

ターゲット URL を書き直す

ここでは、リクエスト本文からデータを抽出し、それをフロー変数に格納して、そのフロー変数をプロキシフローの他の場所で使用する一般的なユースケースを紹介します。たとえば、ユーザーが HTML フォームに名前を入力して送信するアプリがあるとしましょう。そして API プロキシにフォームのデータを抽出させ、バックエンド サービスを呼び出すために使用する URL に動的に追加させるようにしたいとします。これを JavsScript ポリシーではどのように実現するでしょうか?

注: この例を試してみる場合は、新しいプロキシがプロキシ エディタで作成されている必要があります。作成するときは、バックエンド サービス URL: http://www.example.com を指定してください。この例では、バックエンド URL を動的に書き直します。新しいプロキシを作成する方法がわからない場合は、開始チュートリアルを参照してください。

  1. Edge UI で、プロキシ エディタで作成したプロキシを開きます。
  2. [Develop] タブを選択します。
  3. [New] メニューで、[New Script] を選択します。
  4. ダイアログで、JavaScript を選択し、スクリプトに js-example のような名前を付けます。
  5. 以下のコードをコードエディタに貼り付けて、プロキシを保存します。ここで重要なのは context オブジェクトです。このオブジェクトは、プロキシフローのどこにあっても JavaScript コードで使用できます。フロー固有の定数を取得したり、便利な get/set メソッドを呼び出したり、他にも多数の操作に使用します。このオブジェクト部分は、Edge の JavaScript オブジェクト モデルのものです。また、target.url フロー変数は組み込み型の読み込み / 書き込み変数であり、ターゲット リクエスト フローでアクセス可能できる点もご留意ください。この変数を API URL で設定すると、Edge がこの URL に対してバックエンド呼び出しを行います。プロキシを作成したときに指定した元のターゲット URL(http://www.example.com など)は、基本的に書き換えています。

        if (context.flow=="PROXY_REQ_FLOW") {
             var username = context.getVariable("request.formparam.user");
             context.setVariable("info.username", username);
        }
    
        if (context.flow=="TARGET_REQ_FLOW") {
             context.setVariable("request.verb", "GET");
             var name = context.getVariable("info.username");
             var url = "http://mocktarget.apigee.net/"
             context.setVariable("target.url", url + "?user=" + name);
        }
        
  6. [New Policy] メニューで、JavaScript を選択します。
  7. ポリシーに、target-rewrite のような名前を付けます。デフォルト値をそのまま使用して、ポリシーを保存します。
  8. Navigator で Proxy Endpoint Preflow を選択すると、ポリシーがそのフローに追加されたことが表示されます。
  9. Navigator で、[Target Endpoint PreFlow] アイコンを選択します。
  10. Navigator から、JavaScript ポリシーをフローエディタの [Target Endpoint] の [Request] 側へドラッグします。
  11. 保存します。
  12. 以下のようにして API を呼び出します。組織名とプロキシ名は正しいものに適宜置き換えてください。
    curl -i -H 'Content-Type: application/x-www-form-urlencoded' -X POST -d 'user=Will' http://myorg-test.apigee.net/js-example
    

最後に、この例で使用した JavaScript ポリシーの XML 定義を見てみましょう。実行する JavaScript ソースファイルを指定するために <ResourceURL> 要素が使用されている点が重要です。これと同じパターンは、すべての JavaScript ソースファイル(jsc://filename.js)で使用されています。JavaScript コードで include を必要とする場合、このリファレンスで後述するように、1 つ以上の <IncludeURL> 要素を使用できます。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Javascript async="false" continueOnError="false" enabled="true" timeLimit="200" name="target-rewrite">
        <DisplayName>target-rewrite</DisplayName>
        <Properties/>
        <ResourceURL>jsc://js-example.js</ResourceURL>
    </Javascript>
    

JavaScript からプロパティ値を取得する

<Property> 要素を構成で追加して、この要素の値を JavaScript でランタイム時に取得できます。

要素の name 属性を使用して、JavaScript コードのプロパティにアクセスする際の名前を指定します。<Property> 要素の値(開始タグと終了タグの間の値)は、Javacript が受け取るリテラル値です。

JavaScript で、以下のように、Properties オブジェクトのプロパティであるポリシー プロパティ値にアクセスして取得します。

  • プロパティを構成します。ここでは、プロパティ値は変数名 response.status.code です。
        <Javascript async="false" continueOnError="false" enabled="true" timeLimit="200" name="JavascriptURLRewrite">
            <DisplayName>JavascriptURLRewrite</DisplayName>
            <Properties>
                <Property name="source">response.status.code</Property>
            </Properties>
            <ResourceURL>jsc://JavascriptURLRewrite.js</ResourceURL>
        </Javascript>
        
  • プロパティを JavaScript で取得します。ここで、取得した値(変数名)は、getVariable 関数が使用して変数の値を取得します。
        var responseCode = properties.source; // Returns "response.status.code"
        var value = context.getVariable(responseCode); // Get the value of response.status.code
        context.setVariable("response.header.x-target-response-code", value);
        

エラー処理

JavaScript 呼び出しで使用できるエラー処理技法の例と説明については、こちらの Apigee コミュニティの投稿をご覧ください。Apigee コミュニティでお知らせしている提案事項は情報提供のみを目的としたものであり、必ずしも Apigee が推奨するベストプラクティスを示しているわけではありません。


要素リファレンス

要素リファレンスは、JavaScript ポリシーの要素と属性を記述しています。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Javascript async="false"
            continueOnError="false" enabled="true" timeLimit="200"
            name="JavaScript-1">
        <DisplayName>JavaScript 1</DisplayName>
        <Properties>
            <Property name="propName">propertyValue</Property>
        </Properties>
        <SSLInfo>
            <Enabled>trueFalse</Enabled>
            <ClientAuthEnabled>trueFalse</ClientAuthEnabled>
            <KeyStore>ref://keystoreRef</KeyStore>
            <KeyAlias>keyAlias</KeyAlias>
            <TrustStore>ref://truststoreRef</TrustStore>
        </SSLInfo>
        <IncludeURL>jsc://a-javascript-library-file</IncludeURL>
        <ResourceURL>jsc://my-javascript-source-file</ResourceURL>
    </Javascript>
    

<Javascript> 属性

    <Javascript name="Javascript-1" enabled="true" continueOnError="false" async="false" timeLimit="200">
    

以下の属性は、このポリシーに固有のものです。

属性 説明 デフォルト 要否
timeLimit

スクリプトを実行する際に許容される最大時間(ミリ秒)を指定します。

注: 無料トライアル アカウントの場合、実行時間は 200 ミリ秒に制限されます。

なし 必須

次の表に、ポリシーのすべての親要素に共通の属性を記載します。

属性 説明 デフォルト 要否
name

ポリシーの内部名。name 属性の値には、文字、数字、スペース、ハイフン、アンダースコア、ピリオドを使用できます。255 文字を超える値を指定することはできません。

必要に応じて、管理 UI プロキシ エディタで <DisplayName> 要素を使用してポリシーに別のわかりやすい名前でラベルを付けます。

なし 必須
continueOnError

ポリシーが失敗した場合にエラーを返すには、false に設定します。これはほとんどのポリシーで想定される動作です。

ポリシーが失敗してもフロー実行を続行するには、true に設定します。

false 省略可
enabled

ポリシーを適用するには true に設定します。

ポリシーを無効にするには false に設定します。その場合、ポリシーはフローに接続されていているとしても適用されません。

true 省略可
async

この属性は非推奨となりました。

false 非推奨

<DisplayName> 要素

name 属性に加えて、管理 UI プロキシ エディタのポリシーに別のわかりやすい名前でラベルを付けるために使います。

<DisplayName>Policy Display Name</DisplayName>
デフォルト:

なし

この要素を省略した場合、ポリシーの name 属性の値が使用されます

要否: 省略可
型: 文字列

<IncludeURL> 要素

<ResourceURL> 要素で指定されているメインの JavaScript ファイルとの依存関係として読み込まれる JavaScript ライブラリ ファイルを指定します。スクリプトは、ポリシーにリストされている順番で評価されます。コードは、JavaScript オブジェクト モデルのオブジェクト、メソッド、プロパティを使用します。

追加の <IncludeURL> 要素で複数の JavaScript 依存関係リソースを含めます。

    <IncludeURL>jsc://my-javascript-dependency.js</IncludeURL>
    
デフォルト: なし
要否: 省略可
型: 文字列

サンプル セクションの基本的な例をご覧ください。

<Property> 要素

JavaScript コードからランタイム時にアクセスできるプロパティを指定します。

    <Properties>
        <Property name="propName">propertyValue</Property>
    </Properties>
    
デフォルト: なし
要否: 省略可
型: 文字列

属性

属性 説明 デフォルト 要否
name

プロパティの名前を指定します。

なし 必須。

サンプル セクションの例をご覧ください。

<ResourceURL> 要素

API フローで実行するメインの JavaScript ファイルを指定します。このファイルを API プロキシ スコープ(API プロキシ バンドルの /apiproxy/resources/jsc の下、あるいは API プロキシ エディタのナビゲーション パネルの [スクリプト] セクション)で、あるいは組織または環境スコープで格納して、複数の API プロキシ間で再使用できます。詳しくは、リソース ファイルの説明をご覧ください。コードでは、JavaScript オブジェクト モデルのオブジェクト、メソッド、プロパティを使用できます。

    <ResourceURL>jsc://my-javascript.js</ResourceURL>
    
デフォルト: なし
要否: 必須
型: 文字列

サンプル セクションの基本的な例をご覧ください。

<SSLInfo> 要素

JavaScript ポリシーにより作成されたすべての HTTP クライアント インスタンスに TLS を構成するために使用するプロパティを指定します。

        <SSLInfo>
            <Enabled>trueFalse</Enabled>
            <ClientAuthEnabled>trueFalse</ClientAuthEnabled>
            <KeyStore>ref://keystoreRef</KeyStore>
            <KeyAlias>keyAlias</KeyAlias>
            <TrustStore>ref://truststoreRef</TrustStore>
        </SSLInfo>
    
デフォルト: なし
要否: 省略可
型: 文字列

HTTP クライアントに TLS を構成するプロセスは、TargetEndpoint/TargetServer に TLS を構成するために使用するプロセスと同じです。詳細については、Edge からバックエンドへの TLS の構成をご覧ください。

HTTP クライアントの作成について詳しくは、HTTP クライアントを JavaScript で実装するをご覧ください。

使用上の注意

JavaScript ポリシーに実際のコードは含まれません。その代わりに、JavaScript ポリシーは JavaScript の「リソース」を参照し、JavaScript を実行する API フローにステップを定義します。スクリプトは、管理 UI プロキシ エディタを通じてアップロードするか、ローカルで開発している API プロキシの /resources/jsc ディレクトリに含めることができます。

JavaScript ポリシーコードのデバッグ

print() 関数を使用して、デバッグ情報を Trace ツールのトランザクション出力パネルに出力します。詳細と例については、JavaScript の print() ステートメントによるデバッグをご覧ください。

print ステートメントを Trace で表示するには、次の手順を実行します。

  1. Trace ツールを開き、JavaScript ポリシーを含むプロキシのトレース セッションを開始します。
  2. プロキシを呼び出します。
  3. Trace ツールで、[Output from all Transactions] をクリックして出力パネルを開きます。

  4. print ステートメントはこのパネルに表示されます。

print() 関数を使用して、デバッグ情報を Trace ツールに出力できます。この関数は、JavaScript オブジェクト モデルで直接使用できます。詳細については、JavaScript の print() ステートメントによるデバッグをご覧ください。

フロー変数

このポリシーは、デフォルトでは変数に何も入力しません。ただし、JavaScript コードでフロー変数を設定(および取得)できます。その場合は、コンテキスト オブジェクトでメソッドを呼び出します。一般的なパターンは以下のようになります。

    context.setVariable("response.header.X-Apigee-Target", context.getVariable("target.name"))
    

コンテキスト オブジェクトは、Apigee Edge JavaScript オブジェクト モデルの一部です。

エラー リファレンス

このセクションでは、このポリシーでエラーをトリガーしたときに返される障害コードとエラー メッセージ、そして Edge によって設定される障害変数について説明します。これは、障害に対処する障害ルールを作成する上で重要な情報です。詳細については、ポリシーエラーについて知っておくべきこと障害の処理をご覧ください。

ランタイム エラー

ポリシーの実行時に、以下のエラーが発生することがあります。

障害コード HTTP ステータス 原因 修正
steps.javascript.ScriptExecutionFailed 500 JavaScript ポリシーは、さまざまな種類の ScriptExecutionFailed エラーをスローする可能性があります。一般的に見られるエラーの種類は、RangeErrorReferenceErrorSyntaxErrorTypeErrorURIError などです。 build
steps.javascript.ScriptExecutionFailedLineNumber 500 JavaScript コードで発生したエラー。詳細については、障害の文字列をご覧ください。 なし
steps.javascript.ScriptSecurityError 500 JavaScript の実行時に発生したセキュリティ エラー。詳細については、障害の文字列をご覧ください。 なし

デプロイエラー

このポリシーを含むプロキシをデプロイすると、次のエラーが発生することがあります。

エラー名 原因 修正
InvalidResourceUrlFormat JavaScript ポリシーの <ResourceURL> 要素または <IncludeURL> 要素に指定されたリソース URL の形式が無効な場合、API プロキシのデプロイは失敗します。 build
InvalidResourceUrlReference <ResourceURL> 要素または <IncludeURL> 要素が存在しない JavaScript ファイルを参照すると、API プロキシのデプロイは失敗します。参照先のソースファイルは、API プロキシ、環境、組織のいずれかのレベルに、存在する必要があります。 build
WrongResourceType このエラーは、デプロイ時に JavaScript ポリシーの <ResourceURL> 要素または <IncludeURL> 要素が、jsc(JavaScript ファイル)以外のリソースタイプを参照している場合に発生します。 build
NoResourceURLOrSource <ResourceURL> 要素が宣言されていない場合、またはリソース URL がこの要素内で定義されていない場合に、JavaScript ポリシーのデプロイがこのエラーで失敗する可能性があります。 <ResourceURL> 要素は必須の要素です。また、<IncludeURL> 要素が宣言されていても、この要素内でリソース URL が定義されていない場合に発生することもあります。<IncludeURL> 要素は省略することもできますが、宣言されている場合は <IncludeURL> 要素内でリソース URL を指定する必要があります。 build

障害変数

このポリシーがランタイム時にエラーのトリガーとなった場合は、次の変数が設定されます。詳細については、ポリシーエラーについて知っておくべきことをご覧ください。

変数 説明
fault.name="fault_name" fault_name は、上記のランタイム エラー表に記載されている障害の名前です。障害コードの最後の部分が障害名になります。 fault.name Matches "ScriptExecutionFailed"
javascript.policy_name.failed policy_name は、障害をスローしたポリシーにユーザーが指定した名前です。 javascript.JavaScript-1.failed = true

エラー レスポンスの例

    {
      "fault": {
        "faultstring": "Execution of SetResponse failed with error: Javascript runtime error: "ReferenceError: "status" is not defined. (setresponse.js:6)\"",
        "detail": {
          "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
      }
    }
    

障害ルールの例

    <FaultRule name="JavaScript Policy Faults">
        <Step>
            <Name>AM-CustomErrorResponse</Name>
            <Condition>(fault.name Matches "ScriptExecutionFailed") </Condition>
        </Step>
        <Condition>(javascript.JavaScript-1.failed = true) </Condition>
    </FaultRule>
    

スキーマ

ポリシータイプは XML スキーマ(.xsd)で定義されます。GitHub に参照用のポリシー スキーマが用意されています。

関連トピック

Apigee コミュニティの記事

Apigee コミュニティでは以下の関連記事を見つけることができます。