JavaScript ポリシー

このページの内容は ApigeeApigee ハイブリッドに該当します。

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

ポリシー アイコン

概要

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

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

説明

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

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

JavaScript ポリシーでは、実行する JavaScript ソースファイルを指定できます。また、<Source> 要素を使用して、ポリシーの構成に直接 JavaScript コードを組み込むことができます。いずれの場合も、ポリシーに関連付けられているステップが実行されると JavaScript コードが実行されます。ソースファイル オプションでは、ソースコードは常にプロキシ バンドル内の標準の場所(apiproxy/resources/jsc)に格納されます。ソースコードを環境レベルまたは組織レベルのリソース ファイルに保存することもできます。手順については、リソース ファイルをご覧ください。Apigee UI プロキシ エディタから JavaScript をアップロードすることもできます。

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

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

動画

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

サンプル

ターゲット URL を書き直す

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

  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(例: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 から、[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> 属性

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

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

属性 説明 デフォルト 要否
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 ツールのトランザクション出力パネルに出力します。詳細と例については、JavaScript の print() ステートメントを使用したデバッグをご覧ください。

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

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

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

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

フロー変数

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

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

コンテキスト オブジェクトは 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 コミュニティでご覧いただけます。