JavaScript ポリシー

このページは ApigeeApigee ハイブリッドに適用されます。

Apigee Edge のドキュメントを表示する。

JavaScript ポリシーを使用すると、API プロキシフローのコンテキストで実行されるカスタム JavaScript コードを追加できます。このポリシーを使用すると、Apigee ポリシーでカバーされていないカスタム動作を実装できます。

カスタム JavaScript コードでは、Apigee JavaScript オブジェクト モデルのオブジェクト、メソッド、プロパティを使用できます。プロキシ フロー コンテキストで変数の取得、設定、削除、カスタム ロジックの実行、障害処理の実施、リクエストやレスポンスからのデータの抽出、バックエンド ターゲット URL の動的編集を行うことができます。オブジェクト モデルで使用できる基本的な暗号機能を使用することもできます。

JavaScript ポリシーでは、実行する JavaScript ソースファイルを指定できます。また、<Source> 要素を使用して、ポリシーの構成に直接 JavaScript コードを組み込むことができます。いずれの場合も、ポリシーが関連付けられているステップが実行されると JavaScript コードが実行されます。

ソースファイル オプションでは、ソースコードは常にプロキシ バンドル内の標準の場所(apiproxy/resources/jsc)に格納されます。ソースコードを環境レベルまたは組織レベルのリソース ファイルに保存することもできます。手順については、リソース ファイルをご覧ください。Apigee UI プロキシ エディタを使用して JavaScript をアップロードすることもできます。

Apigee では、次の目的で JavaScript ポリシーを使用することをおすすめしません。

  • Logging。MessageLogging ポリシーは、Splunk、Sumo、Loggly などのサードパーティのロギング プラットフォームでのロギングに適しています。このポリシーは、レスポンスがクライアントに返された後に PostClientFlow で実行されるため、API プロキシのパフォーマンスも向上させます。
  • Apigee ポリシーの置き換え。JavaScript ポリシーは、Apigee ポリシーの機能を置き換えるものではありません。必要な機能が Apigee ポリシーで利用可能な場合は、カスタム JavaScript ソリューションを実装する代わりに、そのポリシーを使用します。カスタム JavaScript コードは、Apigee ポリシーのパフォーマンスと最適化に匹敵しない可能性があります。

JavaScript ソースファイルには .js という拡張子を付ける必要があります。

Apigee では、Rhino JavaScript エンジン 1.7.13 で実行される JavaScript をサポートしています。

このポリシーは拡張可能なポリシーであり、Apigee ライセンスによっては、このポリシーの使用によって費用や使用量に影響する場合があります。ポリシータイプと使用量への影響については、ポリシータイプをご覧ください。

サンプル

ターゲット URL を書き直す

一般的なユースケースでは、リクエスト本文からデータを抽出し、フロー変数に保存して、そのフロー変数をプロキシフローの他の場所で使用します。たとえば、ユーザーが HTML フォームに名前を入力して送信するとします。フォームのデータを抽出してバックエンド サービスの URL に動的に追加するには、JavaScript ポリシーを使用します。

  1. Apigee UI で、プロキシ エディタで作成したプロキシを開きます。
  2. [Develop] タブを選択します。
  3. [New] メニューから [New Script] を選択します。
  4. ダイアログで JavaScript を選択し、スクリプトに js-example という名前を付けます。
  5. 次のコードをコードエディタに貼り付けて、プロキシを保存します。context オブジェクトは、プロキシフローのどこにあっても JavaScript コードで使用できます。フロー固有の定数を取得したり、便利な get/set メソッドを呼び出したり、その他のオペレーションを実行したりします。このオブジェクトは、Apigee JavaScript オブジェクト モデルの一部です。target.url フロー変数は、ターゲット リクエスト フローでアクセスできる組み込みの読み取り/書き込み変数です。この変数を API URL に設定すると、Apigee はそのバックエンド URL を呼び出します。これにより、元のターゲット 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. [ナビゲータ] で [Proxy Endpoint Preflow] を選択すると、そのフローにポリシーが追加されます。
  9. [Navigator] で、[Target Endpoint PreFlow] を選択します。
  10. フローエディタの [Navigator] から、[Target Endpoint] の [Request] 側に JavaScript ポリシーをドラッグします。
  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 定義を見てみましょう。<ResourceURL> 要素は、実行する JavaScript ソースファイルを指定します。このパターンは、すべての JavaScript ソースファイル(jsc://filename.js)に適用されます。JavaScript コードでインクルードが必要な場合は、このドキュメントで後述するように、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> 要素の値(開始タグと終了タグの間の値)は、JavaScript が受け取るリテラル値です。

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 コールアウトで使用できるエラー処理手法の例については、 JavaScript ポリシーからエラーを返す正しい方法をご覧ください。Apigee コミュニティでお知らせしている提案事項は情報提供のみを目的としたものであり、必ずしも Google が推奨するベスト プラクティスではありません。

要素リファレンス

要素リファレンスは、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>
    <Source>insert_js_code_here</Source>
</Javascript>

<Javascript> 属性

< languageVersion="VERSION_1_3" Javascript name="Javascript-1" enabled="true" continueOnError="false" async="false" timeLimit="200">
属性 説明 デフォルト 要否
languageVersion

コードが記述されている JavaScript 言語のバージョンを指定します。値には、VERSION_DEFAULTVERSION_1_0VERSION_1_1VERSION_1_2VERSION_1_3VERSION_1_4VERSION_1_5VERSION_1_6VERSION_1_7VERSION_1_8VERSION_ES6 などがあります。

VERSION_DEFAULT 省略可
timeLimit

スクリプトを実行できる最大時間(ミリ秒)を指定します。たとえば、200 ミリ秒の上限を超えると、ポリシーはエラー Javascript.policy_name failed with error: Javascript runtime exceeded limit of 200ms をスローします。

なし 必須

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

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

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

管理 UI プロキシ エディタで <DisplayName> 要素を追加して、ポリシーのラベルに使用する別の自然言語名を指定することもできます。

なし 必須
continueOnError

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

ポリシーが失敗した後もフローの実行を続行する場合は、true に設定します。関連項目:

false 省略可
enabled

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

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

true 省略可
async

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

false 非推奨

<DisplayName> 要素

管理 UI プロキシ エディタで name 属性と一緒に使用して、ポリシーのラベルに使用する自然言語名を指定します。

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

なし

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

要否 省略可
タイプ 文字列

<IncludeURL> 要素

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

複数の JavaScript 依存関係リソースを含めるには、追加の <IncludeURL> 要素を使用します。

<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 プロキシ エディタの [Navigator] ペインの [Scripts] セクション)に保存できます。または、リソースの管理の説明に従って、組織または環境スコープに保存して、複数の API プロキシ間で再利用することもできます。コードでは、JavaScript オブジェクト モデルのオブジェクト、メソッド、プロパティを使用できます。

<ResourceURL>jsc://my-javascript.js</ResourceURL>
デフォルト: なし
要否: <ResourceURL> または <Source> が必須。<ResourceURL><Source> の両方が存在する場合、ポリシーは <ResourceURL> を無視します。
型: 文字列

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

<Source> 要素

ポリシーの XML 構成に直接 JavaScript を挿入できます。挿入された JavaScript コードは、ポリシーが API フローで実行された際に実行されます。

デフォルト: なし
要否: <ResourceURL> または <Source> が必須。<ResourceURL><Source> の両方が存在する場合、ポリシーは <ResourceURL> を無視します。
型: 文字列

<Javascript name='JS-ParseJsonHeaderFullString' timeLimit='200' >
  <Properties>
    <Property name='inboundHeaderName'>specialheader</Property>
    <Property name='outboundVariableName'>json_stringified</Property>
  </Properties>
  <Source>
var varname = 'request.header.' + properties.inboundHeaderName + '.values.string';
var h = context.getVariable(varname);
if (h) {
  h = JSON.parse(h);
  h.augmented = (new Date()).valueOf();
  var v = JSON.stringify(h, null, 2) + '\n';
  // further indent
  var r = new RegExp('^(\S*)','mg');
  v= v.replace(r,'    $1');
  context.setVariable(properties.outboundVariableName, v);
}
  </Source>
</Javascript>

<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 を構成するプロセスと同じです。詳細については、TLS の構成オプションをご覧ください。

使用上の注意

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

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

Debug ツールで print ステートメントを表示するには:

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

    Apigee Trace ツールの [Output from all Transactions] パネルに、print ステートメントが表示されている。

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

フロー変数

このポリシーは、デフォルトでは変数に何も挿入しません。ただし、context オブジェクトでメソッドを呼び出すことで、JavaScript コードでフロー変数を設定して取得できます。次に例を示します。

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

context オブジェクトは、Apigee JavaScript オブジェクト モデルの一部です。

エラー リファレンス

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

ランタイム エラー

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

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

デプロイエラー

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

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

障害変数

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

変数 説明
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 コミュニティでご覧いただけます。