JavaScript 政策

本页面适用于 ApigeeApigee Hybrid

查看 Apigee Edge 文档。

政策图标

内容

此政策允许您添加在 API 代理流上下文中执行的自定义 JavaScript 代码。在自定义 JavaScript 代码中,您可以使用 Apigee JavaScript 对象模型的对象、方法和属性。对象模型让您可在代理流上下文中获取、设置和移除变量。您还可以使用随对象模型提供的基本加密函数。

此政策是一项可扩展政策,使用此政策可能会影响费用或使用情况,具体取决于您的 Apigee 许可。如需了解政策类型和使用情况影响,请参阅政策类型

关于

JavaScript 政策有许多用例。例如,您可以获取和设置流变量,执行自定义逻辑并执行故障处理,从请求或响应中提取数据,动态编辑后端目标网址,等等。该政策让您可实施任何其他标准 Apigee 政策未涵盖的自定义行为。实际上,您可以使用 JavaScript 政策来实现其他政策实施的许多行为,如 AssignMessage 和 ExtractVariable。

对于 JavaScript 政策,我们不建议的用例是日志记录。MessageLogging 政策更适合记录到 Splunk,Sumo 和 Loggly 等第三方日志记录平台,并且您可通过在 PostClientFlow 中执行 MessageLogging 政策来提高 API 代理性能。PostClientFlow 在将响应发送回客户端后执行。

JavaScript 政策让您可以指定要执行的 JavaScript 源文件,或者您可以使用 <Source> 元素直接在政策的配置中添加 JavaScript 代码。无论采用哪种方式,JavaScript 代码在执行政策关联的步骤时都会执行。对于源文件选项,源代码始终存储在代理软件包中的标准位置:apiproxy/resources/jsc。或者,您也可以将源代码存储在环境或组织级层的资源文件中。如需了解相关说明,请参阅资源文件。您还可以通过 Apigee 界面代理编辑器上传 JavaScript。

JavaScript 源文件必须始终具有 .js 扩展名。

Apigee 支持在 Rhino JavaScript 引擎 1.7.13 上运行的 JavaScript。

视频

观看短视频,了解如何使用 JavaScript 政策创建自定义政策扩展程序。

示例

重写目标网址

下面是一个常见的用例:从请求正文中提取数据,将其存储在流变量中,并在代理流的其他位置使用该流变量。假设您有一个应用,用户可以在 HTML 表单中输入其名称并提交该名称。您希望 API 代理提取表单数据,并将其动态添加到用于调用后端服务的网址。如何在 JavsScript 政策中执行此操作?

  1. 在 Apigee 界面中,打开您在代理编辑器中创建的代理。
  2. 选择开发标签页。
  3. 从“新建”菜单中,选择新建脚本
  4. 在对话框中,选择 JavaScript 并为脚本命名,例如 js-example
  5. 将以下代码粘贴到代码编辑器中,并保存代理。需要注意的是 context 对象。在代理流中的任何位置,您都可以在 JavaScript 代码中使用此对象。它用于获取流特定常量、调用有用的 get/set 方法以及执行更多操作。此对象部分属于 Apigee JavaScript 对象模型。另请注意,target.url 流变量是内置的读/写变量,可通过目标请求流访问。当我们使用 API 网址设置该变量时,Apigee 会对该网址执行后端调用。我们实质上重写了原始目标网址,也就是您在创建代理时指定的网址(例如,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. 从“新建政策”菜单中,选择 JavaScript
  7. 为政策命名,例如 target-rewrite。接受默认值并保存政策。
  8. 如果您在导航工具中选择代理端点 Preflow,将看到该政策已添加到该流中。
  9. 在导航工具中,选择目标端点 PreFlow 图标。
  10. 在导航工具中,将 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 代码要求包含,则可以使用一个或多个 <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">

以下属性特定于此政策。

属性 说明 默认 Presence
timeLimit

指定允许脚本执行的最长时间(以毫秒为单位)。例如,如果超出 200 毫秒的限制,则政策会引发以下错误:Javascript.policy_name failed with error: Javascript runtime exceeded limit of 200ms

不适用 必需

下表介绍了所有政策父元素通用的特性:

属性 说明 默认 Presence
name

政策的内部名称。name 属性的值可以包含字母、数字、空格、连字符、下划线和英文句点。此值不能超过 255 个字符。

(可选)使用 <DisplayName> 元素在管理界面代理编辑器中给政策添加不同的自然语言名称标签。

不适用 必需
continueOnError

设置为 false 可在政策失败时返回错误。这是大多数政策的预期行为。

设置为 true,即使在政策失败后,仍可以继续执行流。另请参阅:

false 可选
enabled

设置为 true 可强制执行政策。

设为 false关闭政策。即使政策仍附加到某个流,也不会强制执行该政策。

true 可选
async

此特性已弃用。

false 已弃用

<DisplayName> 元素

用于在 name 属性之外在管理界面代理编辑器中给政策添加不同的自然语言名称标签。

<DisplayName>Policy Display Name</DisplayName>
默认

不适用

如果省略此元素,则会使用政策的 name 属性的值。

Presence 可选
类型 字符串

<IncludeURL> 元素

指定要作为使用 <ResourceURL><Source> 元素指定的主要 JavaScript 文件的依赖项加载的 JavaScript 库文件。脚本将按政策中的列出顺序进行评估。您的代码可以使用 JavaScript 对象模型的对象、方法和属性。

使用附加 <IncludeURL> 元素添加多个 JavaScript 依赖项资源。

<IncludeURL>jsc://my-javascript-dependency.js</IncludeURL>
默认:
状态: 可选
类型: 字符串

示例

请参阅示例部分中的“基本示例”。

<Property> 元素

指定可在运行时从 JavaScript 代码访问的属性。

<Properties>
    <Property name="propName">propertyValue</Property>
</Properties>
默认:
状态: 可选
类型: 字符串

属性

属性 说明 默认 Presence
name

指定属性的名称。

不适用 必填。

示例

请参阅示例部分中的示例。

<ResourceURL> 元素

指定将在 API 流中执行的主要 JavaScript 文件。您可以在 API 代理范围(API 代理软件包的 /apiproxy/resources/jsc 下方或 API 代理编辑器导航工具窗格的“脚本”部分中)或组织或环境范围中存储此文件,以便在多个 API 代理中重复使用,如管理资源中所述。您的代码可以使用 JavaScript 对象模型的对象、方法和属性。

<ResourceURL>jsc://my-javascript.js</ResourceURL>
默认:
状态: 必须提供 <ResourceURL><Source>。如果 <ResourceURL><Source> 同时存在,则系统会忽略 <ResourceURL>
类型: 字符串

示例

请参阅示例部分中的“基本示例”。

<Source> 元素

允许您将 JavaScript 直接插入到政策的 XML 配置中。插入的 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() 函数将调试信息输出到调试工具中的事务输出面板。如需了解详情和示例,请参阅使用 JavaScript print() 语句进行调试。

要在调试工具中查看 print 语句,请执行以下操作:

  1. 打开调试工具并为包含 JavaScript 政策的代理启动跟踪会话。
  2. 调用代理。
  3. 在调试工具中,点击从所有事务输出 (Output from all Transactions) 以打开输出面板。

  4. 您的 print 语句将显示在此面板中。

您可以使用 print() 函数将调试信息输出到调试工具。此函数可直接通过 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> 元素中指定的资源网址格式无效,则 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>

架构

每种政策类型均由 XML 架构 (.xsd) 定义。GitHub 提供了政策架构作为参考。

相关主题

Apigee 社区文章

您可以在 Apigee 社区中找到以下相关文章: