使用 JavaScript 编程 API 代理

您正在查看 Apigee Edge 文档。
请查看 Apigee X 文档

在本主题中,您将学习如何使用 JavaScript 向响应消息动态添加 HTTP 标头,以及如何解析 JSON 响应并将其部分属性返回给发出请求的应用。

下载并试用示例代码

关于此食谱示例

本实战示例展示了您在 JavaScript 中实现 API 行为的 API 代理模式。JavaScript 示例旨在说明如何使用简单的变量和消息内容。一个示例展示了如何获取设置变量。第二个示例展示了如何解析 JSON 并根据结果构建消息。

API 代理中有两个 JavaScript 示例:

  • setHeaders.js:此 JavaScript 会获取调用 API 代理时设置的几个变量的值。JavaScript 会将这些变量添加到响应消息中,以便您查看发出的每个请求的值。
  • minimize.js:此 JavaScript 展示了如何处理消息内容。此示例背后的理念是服务返回的数据通常超过必要数量。因此,JavaScript 会解析响应消息,提取一些有趣的属性,然后使用这些属性来构建响应消息的内容。

setHeader.js 的代码如下:

context.setVariable("response.header.X-Apigee-Target", context.getVariable("target.name"));
context.setVariable("response.header.X-Apigee-ApiProxyName", context.getVariable("apiproxy.name"));
context.setVariable("response.header.X-Apigee-ProxyName", context.getVariable("proxy.name"));
context.setVariable("response.header.X-Apigee-ProxyBasePath", context.getVariable("proxy.basepath"));
context.setVariable("response.header.X-Apigee-ProxyPathSuffix", context.getVariable("proxy.pathsuffix"));
context.setVariable("response.header.X-Apigee-ProxyUrl", context.getVariable("proxy.url"));

minimize.js 的代码如下:

//Parse the respose from the target.
var res = JSON.parse(context.proxyResponse.content);

//Pull out only the information we want to see in the response.
var minimizedResponse = { city: res.root.city,
                          state: res.root.state };
          
//Set the response variable. 
context.proxyResponse.content = JSON.stringify(minimizedResponse);

您可以通过上下文对象在 JavaScript 中访问流变量。此对象是 Edge JavaScript 对象模型的一部分。如需详细了解对象模型,请参阅 JavaScript 对象模型

须知事项

在探索此实战宝典示例之前,您还应该熟悉以下基本概念:

  • 什么是政策以及如何将政策附加到代理。如需深入了解政策,请参阅什么是政策?
  • 代理流的结构,如配置流中所述。流程允许您指定 API 代理执行政策的顺序。在此示例中,我们创建了多项政策并将其添加到 API 代理流程中。
  • API 代理项目在文件系统中的组织方式,如 API 代理配置参考文档中所述。
  • 具备 XML、JSON 和 JavaScript 方面的实践知识。在此示例中,您将使用位于文件系统上的 XML 文件来构建 API 代理及其政策。

如果您已下载示例代码,则可以在 javascript-cookbook 示例文件夹中找到本主题中讨论的所有文件。以下部分详细介绍了示例代码。

了解代理流程

如需在 API 代理中执行 JavaScript,您必须使用名为“步骤”的政策连接来将其附加到数据流。JavaScript 类型的政策(注意大小写)仅包含对 JavaScript 文件名称的引用。您使用 Resource网址 元素将该政策指向 JavaScript 文件。

例如,以下政策会引用名为 setHeader.js 的 JavaScript 文件。

<Javascript name='setHeaders' timeLimit='200'>
    <ResourceURL>setHeaders.js</ResourceURL>
</Javascript>

您可以像设置任何其他政策类型一样将此政策附加到 API 代理流程。通过将该政策附加到 API 代理流程,可指明 JavaScript 的执行位置。 这样,您就可以执行与请求消息或响应消息交互的 JavaScript,当这些消息通过 API 代理“流”时。在此示例中,两个 JavaScript 都在响应流程中执行,因为政策会执行两项操作:在响应消息上设置 HTTP 标头,以及“最小化”Apigee 返回给请求应用的响应消息。

如果您在管理界面中打开此数据流配置,则会看到下方的数据流配置。

Navigator 窗格中依次选择 Proxy Endpoints > default > PostFlow

下方显示了名为“default”的代理端点的相应 XML 配置。

<ProxyEndpoint name="default">
  <PostFlow>
    <Response>
      <!-- Steps reference policies under /apiproxy/policies -->
      <!-- First, set a few HTTP headers with variables for this transaction. -->
      <Step><Name>setHeaders</Name></Step>
      <!-- Next, transform the response from XML to JSON for easier parsing with JavaScript -->
      <Step><Name>transform</Name></Step>
      <!-- Finally, use JavaScript to create minimized response with just city and state. -->
      <Step><Name>minimize</Name></Step>
    </Response>
  </PostFlow>
  <HTTPProxyConnection>
        <!-- BasePath defines the network address for this API proxy. See the script 'invoke.sh' to see how the complete URL for this API proxy is constructed.-->
    <BasePath>/javascript-cookbook</BasePath>
     <!-- Set VirtualHost to 'secure' to have this API proxy listen on HTTPS. -->
    <VirtualHost>default</VirtualHost>
  </HTTPProxyConnection>
  <RouteRule name="default">
    <TargetEndpoint>default</TargetEndpoint>
  </RouteRule>
</ProxyEndpoint>

下面是 flow 元素的摘要。

  • <Request> - <Request> 元素由多个 <Step> 元素组成。每个步骤都会调用您通过本主题其余部分创建的某项政策。这些政策会将 JavaScript 附加到 API 代理流程,而政策连接的位置决定了 JavaScript 的执行时间。
  • <Response> - <Response> 元素还包含 <Steps>。这些步骤还会调用负责处理目标的最终响应的政策(在此示例中是 Apigee 的模拟服务目标 - 请注意 /apiproxy/targets/default.xml 下的 HTTPTargetConnection 设置)。
  • <HTTPProxyConnection> - 指定主机和 URI 路径,路径用于定义应用调用使用此 API 的网络地址。
  • <RouteRule> - 此元素指定代理端点调用的 TargetEndpoint 配置。

将 JavaScript 代码添加到代理

JavaScript(如 Python 脚本、Java JAR 文件、XSLT 文件等)以资源的形式存储。如果您刚开始使用 JavaScript,最简单的方法是将 JavaScript 文件存储在 API 代理中。在此过程中,您应将 JavaScript 设置为通用且可重复使用,然后存储在环境组织级别。这样一来,您就不必将相同的 JavaScript 文件存储在多个 API 代理中,这就很快会造成无法管理。

如需了解如何在组织和环境级别存储资源,请参阅资源文件

试试看

有关部署和调用代理的说明,请参阅 JavaScript 实战宝典自述文件

导入和部署 API 代理

做出更改后,您可以在管理界面的 API 代理构建工具中保存 API 代理。

或者,您也可以在 /api-platform-samples/doc-samples/javascript-cookbook 目录中运行以下命令。

$ sh deploy.sh

测试 JavaScript

在目录 /api-platform-samples/doc-samples/javascript-cookbook 中运行以下命令。

$ sh invoke.sh

curl 标志 -v 用于 shell 脚本,以查看 JavaScript 修改的响应消息上的 HTTP 标头。

您可以直接按如下所示提交请求:

$ curl -v http://{org_name}-test.apigee.net/javascript-cookbook 

如果 JavaScript 正确执行,您会看到如下所示的响应:

< X-Apigee-Demo-Target: default
< X-Apigee-Demo-ApiProxyName: simple-javascript
< X-Apigee-Demo-ProxyName: default
< X-Apigee-Demo-ProxyBasePath: /javascript-cookbook
< X-Apigee-Demo-ProxyPathSuffix: /xml
< X-Apigee-Demo-ProxyUrl: http://rrt331ea.us-ea.4.apigee.com/javascript-cookbook/xml
 
{"city":"San Jose","state":"CA"}

现在,您可以修改 JavaScript 以尝试新方法、重新部署 API 代理,以及通过提交同一请求来验证结果。请务必部署包含 JavaScript 的 API 代理,以使您所做的更改生效。

脚本错误

编写 JavaScript 时,您必然会看到错误。下方显示了由 API 代理发出的 JavaScript 错误的格式。

{  
   "fault":{  
      "faultstring":"Execution of rewriteTargetUrl failed with error: Javascript runtime error: \"TypeError: Cannot find function getVariable in object TARGET_REQ_FLOW. (rewriteTargetUrl_js#1). at line 1 \"",
      "detail":{  
         "errorcode":"steps.javascript.ScriptExecutionFailed"
      }
   }
}

何时使用 JavaScript

在 Apigee Edge 中,可实现特定功能的方式通常不止一种。尽可能使用开箱即用的政策,并避免用 JavaScript 对所有 API 代理逻辑进行编码。尽管 Apigee Edge 使用编译后的 JavaScript 来提升性能,但 JavaScript 的效果可能不及政策。JavaScript 可能更难以维护和调试。预留 JavaScript 以实现符合您要求的功能。

如果性能关乎自定义功能,请尽可能使用 Java。

总结

在本实战宝典主题中,您学习了如何将 JavaScript 添加到 API 代理配置中以实现自定义行为。这些示例实现的自定义行为说明了如何获取和变量,以及如何解析 JSON 和构建自定义响应消息。