JavaScript policy

Extensible policy

This page applies to Apigee and Apigee hybrid.

View Apigee Edge documentation.

The JavaScript policy lets you add custom JavaScript code that executes in the context of the API proxy flow. This policy lets you implement custom behavior not otherwise covered by Apigee policies.

In your custom JavaScript code, you can use the objects, methods, and properties of the Apigee JavaScript object model. You can get, set, and remove variables in the proxy flow context, execute custom logic, perform fault handling, extract data from requests or responses, and dynamically edit the backend target URL. You can also use basic cryptographic functions that are available in the object model.

The JavaScript policy lets you specify a JavaScript source file to execute, or you can include JavaScript code directly in the policy's configuration using the <Source> element. Either way, the JavaScript code executes when the step where the policy is attached executes.

For the source file option, the source code is always stored in a standard location in the proxy bundle: apiproxy/resources/jsc. Or, you can store the source code in a resource file at the environment or organization level. For instructions, see Resource files. You can also upload JavaScript using the Apigee UI proxy editor.

JavaScript source files must have a .js extension. Apigee supports JavaScript running on the Rhino JavaScript engine 1.7.13.

Apigee does not recommend using the JavaScript policy for the following:

  • Logging. The MessageLogging policy is better suited for logging with third-party logging platforms such as Splunk, Sumo, and Loggly. This policy also improves API proxy performance by executing in the PostClientFlow after the response returns to the client.
  • Replacing Apigee policies. The JavaScript policy does not replace the capabilities of Apigee policies. If the capabilities you need are available in an Apigee policy, use that policy instead of implementing a custom JavaScript solution. Custom JavaScript code might not match the performance and optimization of Apigee policies.
  • To perform system calls. The security model does not permit system calls from the JavaScript policy. For example, internal file system reads or writes, current user information, process lists, or CPU/memory utilization are not permitted. Although some calls might be functional, they are unsupported and subject to active disablement at any time. For forward compatibility, avoid making these calls in your code.

This policy is an Extensible policy and use of this policy might have cost or utilization implications, depending on your Apigee license. For information on policy types and usage implications, see Policy types.

Samples

Rewrite the target URL

A common use case involves extracting data from a request body, storing it in a flow variable, and then using that flow variable elsewhere in the proxy flow. For example, suppose a user enters their name in an HTML form and submits it. To extract the form data and dynamically add it to the backend service URL, use a JavaScript policy.

  1. In the Apigee UI, open the proxy you created in the proxy editor.
  2. Select the Develop tab.
  3. From the New menu, select New Script.
  4. In the dialog, select JavaScript and name the script js-example.
  5. Paste the following code in the code editor and save the proxy. The context object is available to JavaScript code anywhere in the proxy flow. It obtains flow-specific constants, calls useful get/set methods, and performs other operations. This object is part of the Apigee JavaScript object model. The target.url flow variable is a built-in, read/write variable accessible in the Target Request flow. When you set that variable with the API URL, Apigee calls that backend URL. This rewrites the original target URL, which was the URL you specified when you created the proxy (for example, 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. From the New Policy menu, select JavaScript.
  7. Name the policy target-rewrite. Accept the defaults, and save the policy.
  8. After you select the Proxy Endpoint Preflow in the Navigator, the policy is added to that flow.
  9. In the Navigator, select Target Endpoint PreFlow.
  10. In the Navigator, drag the JavaScript policy onto the Request side of the Target Endpoint in the flow editor.
  11. Save.
  12. Substitute your organization name and proxy name when you call the API:
curl -i -H 'Content-Type: application/x-www-form-urlencoded' -X POST -d 'user=Will' http://myorg-test.apigee.net/js-example

Examine the XML definition for the JavaScript policy used in this example. The <ResourceURL> element specifies the JavaScript source file to execute. This pattern applies to any JavaScript source file: jsc://filename.js. If your JavaScript code requires includes, use one or more <IncludeURL> elements, as described later in this document.

<?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>

Retrieve property value from JavaScript

You can add a <Property> element in the configuration and then retrieve its value with JavaScript at runtime.

Use the element's name attribute to specify the name for accessing the property from JavaScript code. The <Property> element's value (the value between the opening and closing tags) is the literal value JavaScript receives.

In JavaScript, you retrieve the policy property value by accessing it as a property of the Properties object, as follows:

  • Configure the property. The property value is the variable name 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>
  • Retrieve the property using JavaScript. The getVariable function then uses the retrieved variable name to retrieve the variable's value.
    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);

Element reference

The element reference describes the elements and attributes of the JavaScript policy.

<?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> Attributes

< languageVersion="VERSION_1_3" Javascript name="Javascript-1" enabled="true" continueOnError="false" async="false" timeLimit="200">
Attribute Description Default Presence
languageVersion

Specifies the version of the JavaScript language the code is written in. Values include VERSION_DEFAULT, VERSION_1_0, VERSION_1_1, VERSION_1_2, VERSION_1_3, VERSION_1_4, VERSION_1_5, VERSION_1_6, VERSION_1_7, VERSION_1_8, and VERSION_ES6.

VERSION_DEFAULT Optional
timeLimit

Specifies the maximum time (in milliseconds) a script can execute. For example, if a 200 ms limit is exceeded, the policy throws this error: Javascript.policy_name failed with error: Javascript runtime exceeded limit of 200ms.

N/A Required

The following table describes attributes that are common to all policy parent elements:

Attribute Description Default Presence
name

The internal name of the policy. The value of the name attribute can contain letters, numbers, spaces, hyphens, underscores, and periods. This value cannot exceed 255 characters.

Optionally, use the <DisplayName> element to label the policy in the management UI proxy editor with a different, natural-language name.

N/A Required
continueOnError

Set to false to return an error when a policy fails. This is expected behavior for most policies.

Set to true to have flow execution continue even after a policy fails. See also:

false Optional
enabled

Set to true to enforce the policy.

Set to false to turn off the policy. The policy will not be enforced even if it remains attached to a flow.

true Optional
async

This attribute is deprecated.

false Deprecated

<DisplayName> element

Use in addition to the name attribute to label the policy in the management UI proxy editor with a different, natural-language name.

<DisplayName>Policy Display Name</DisplayName>
Default

N/A

If you omit this element, the value of the policy's name attribute is used.

Presence Optional
Type String

<IncludeURL> element

Specifies a JavaScript library file to load as a dependency for the main JavaScript file specified with the <ResourceURL> or <Source> element. The policy evaluates the scripts in the order in which they are listed in the policy. Your code can use the objects, methods, and properties of the JavaScript object model.

Include more than one JavaScript dependency resource using additional <IncludeURL> elements.

<IncludeURL>jsc://my-javascript-dependency.js</IncludeURL>
Default: None
Presence: Optional
Type: String

<Property> element

Specifies a property you can access from JavaScript code at runtime.

<Properties>
    <Property name="propName">propertyValue</Property>
</Properties>
Default: None
Presence: Optional
Type: String

Attributes

Attribute Description Default Presence
name

Specifies the name of the property.

N/A Required

Example

See the example in the Samples section.

<ResourceURL> element

Specifies the main JavaScript file that executes in the API flow. You can store this file at the API proxy scope (under /apiproxy/resources/jsc in the API proxy bundle or in the Scripts section of the API proxy editor's Navigator pane). Alternatively, store it at the organization or environment scopes for reuse across multiple API proxies, as described in Managing resources. Your code can use the objects, methods, and properties of the JavaScript object model.

<ResourceURL>jsc://my-javascript.js</ResourceURL>
Default: None
Presence: Either <ResourceURL> or <Source> is required. If both <ResourceURL> and <Source> are present, the policy ignores <ResourceURL>.
Type: String

Example

See the example in the Samples section.

<Source> element

You can insert JavaScript directly into the policy's XML configuration. The inserted JavaScript code executes when the policy executes in the API flow.

Default: None
Presence: Either <ResourceURL> or <Source> is required. If both <ResourceURL> and <Source> are present, the policy ignores <ResourceURL>.
Type: String

Example

<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> element

Specifies the properties used to configure TLS for all HTTP client instances created by the JavaScript policy.

    <SSLInfo>
        <Enabled>trueFalse</Enabled>
        <ClientAuthEnabled>trueFalse</ClientAuthEnabled>
        <KeyStore>ref://keystoreRef</KeyStore>
        <KeyAlias>keyAlias</KeyAlias>
        <TrustStore>ref://truststoreRef</TrustStore>
    </SSLInfo>
Default: None
Presence: Optional
Type: String

The process of configuring TLS for an HTTP client is the same process used to configure TLS for a TargetEndpoint/TargetServer. See Options for configuring TLS for more information.

Use JavaScript to handle errors

You can use the JavaScript policy to handle and return errors. For a discussion on this topic, see Correct way to return an error from a JavaScript policy in the Apigee Community. Note that community posts and comments do not necessarily represent best practices recommended by Apigee.

Debug JavaScript policy code

Use the print() function to output debug information to the transaction output panel in the Debug tool. For details and examples, see Debug JavaScript with print() statements.

To view print statements in the Debug tool:

  1. Open the Debug tool and start a trace session for a proxy that contains your JavaScript policy.
  2. Call the proxy.
  3. In the Debug Tool, click the JavaScript policy, then the Properties tab to see the "stepExecution-stdout" property showing the print statement output.

    Output from Properties tab in the Debug tool, displaying print statements.

  4. Your print statements appear in this panel.

Flow Variables

This policy does not populate any variables by default. However, you can set and get flow variables in your JavaScript code by calling methods on the context object. For example:

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

The context object is part of the Apigee JavaScript object model.

Error reference

本部分介绍当此政策触发错误时返回的故障代码和错误消息,以及由 Apigee 设置的故障变量。在开发故障规则以处理故障时,请务必了解此信息。如需了解详情,请参阅您需要了解的有关政策错误的信息处理故障

运行时错误

政策执行时可能会发生这些错误。

故障代码 HTTP 状态 原因 修复
steps.javascript.ScriptExecutionFailed 500 JavaScript 政策可能会抛出许多不同类型的 ScriptExecutionFailed 错误。 常见的错误类型包括:RangeErrorReferenceErrorSyntaxErrorTypeErrorURIError
steps.javascript.ScriptExecutionFailedLineNumber 500 JavaScript 代码中出现错误。请参阅故障字符串了解详情。 不适用
steps.javascript.ScriptSecurityError 500 JavaScript 执行时出现安全错误。请参阅故障字符串了解详情。 不适用

部署错误

在您部署包含此政策的代理时,可能会发生这些错误。

错误名称 原因 修复
InvalidResourceUrlFormat 如果 JavaScript 政策的 <ResourceURL><IncludeURL> 元素中指定的资源网址格式无效,则 API 代理的部署将失败。
InvalidResourceUrlReference 如果 <ResourceURL><IncludeURL> 元素引用了不存在的 JavaScript 文件,则 API 代理的部署将失败。引用的源文件必须存在于 API 代理、环境或组织级别。
WrongResourceType 如果 JavaScript 政策的 <ResourceURL><IncludeURL> 元素引用除 jscJavaScript 文件)以外的任何资源类型,则会在部署期间出现此错误。
NoResourceURLOrSource 如果未声明 <ResourceURL> 元素或此元素内未定义资源网址,则 JavaScript 政策的部署可能会失败,并显示此错误。<ResourceURL> 元素是必需元素。或者,声明了 <IncludeURL> 元素,但未在此元素中定义资源网址。<IncludeURL> 元素是可选的,但如果声明,则必须在 <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>

Schema

Each policy type is defined by an XML schema (.xsd). For reference, policy schemas are available on GitHub.

Related topics

Apigee Community articles

You can find these related articles in the Apigee Community: