您正在查看 Apigee Edge 文档。
前往 Apigee X 文档。 信息
在本主题中,您将学习如何使用政策组合创建混搭。 政策组合是一种 Apigee 代理模式,可让您使用政策将多个后端目标的结果合并到单个响应中。
如需大致了解政策组合,请参阅 API 代理 Cookbook 模式中的“政策组合模式”。
下载并试用示例代码
关于此实战宝典示例
此实用指南示例展示了一种名为政策组合的 API 代理模式。此模式提供了一种(还有其他方法)将来自多个后端来源的数据混搭在一起的方法。 更一般地说,本主题展示了如何组合和链接政策以产生所需的结果。如需大致了解此模式和其他相关模式,请参阅 API 代理实战宝典模式。
此处讨论的示例使用政策组合来混搭来自以下两个单独的公共 API 的数据:
- Google Geocoding API:此 API 可将地址(例如“1600 Amphitheatre Parkway, Mountain View, CA”)转换为地理位置坐标(例如,纬度 37.423021 和经度 -122.083739)。
- Google 海拔 API:此 API 提供了一个简单的接口,用于查询地球上各位置的海拔数据。在此示例中,从 Geocoding API 返回的坐标将用作此 API 的输入。

应用开发者将使用两个查询参数(邮政编码和国家/地区 ID)调用此 API 代理:
$ curl "http://{myorg}-test.apigee.net/policy-mashup-cookbook?country=us&postalcode=08008"
响应是一个 JSON 对象,其中包含所提供邮政编码区域中心的地理编码位置(纬度/经度),以及该地理编码位置的海拔高度。
{
"ElevationResponse":{
"status":"OK",
"result":{
"location":{
"lat":"39.7500713",
"lng":"-74.1357407"
},
"elevation":"0.5045232",
"resolution":"76.3516159"
}
}
}准备工作
如果您想简要了解政策组合模式,请参阅 API 代理 Cookbook 模式中的“政策组合模式”。
在探索此 Cookbook 示例之前,您还应熟悉以下基本概念:
- 政策是什么以及如何将其附加到代理。如需简要了解政策,请参阅什么是政策?。
- API 代理流的结构,如配置流中所述。通过流,您可以指定 API 代理执行政策的顺序。在此示例中,系统会创建多项政策并将其添加到 API 代理的流中。
- API 代理项目在文件系统中的组织方式,如 API 代理配置参考中所述。此实操指南主题演示了本地开发(基于文件系统)与基于云的开发之间的区别,在基于云的开发中,您可以使用管理界面来开发 API 代理。
- 使用 API 密钥验证。这是您可以为 API 配置的最简单的基于应用的安全形式。如需了解详情,请参阅 API 密钥。您还可以参阅通过要求 API 密钥保护 API 教程。
- 具备 XML 的实际运用知识。在此示例中,我们将使用文件系统中的 XML 文件构建 API 代理及其政策。
如果您已下载示例代码,则可以在 mashup-policy-cookbook 示例文件夹中找到本主题中讨论的所有文件。以下部分将详细讨论示例代码。
顺其自然
在介绍政策之前,我们先来看看示例 API 代理的主要流程。下面的流 XML 详细介绍了此代理、它使用的政策以及调用这些政策的位置。
在下载的示例中,您可以在文件 doc-samples/policy-mashup-cookbook/apiproxy/proxies/default.xml 中找到此 XML。
<ProxyEndpoint name="default"> <Flows> <Flow name="default"> <Request> <!-- Generate request message for the Google Geocoding API --> <Step><Name>GenerateGeocodingRequest</Name></Step> <!-- Call the Google Geocoding API --> <Step><Name>ExecuteGeocodingRequest</Name></Step> <!-- Parse the response and set variables --> <Step><Name>ParseGeocodingResponse</Name></Step> <!-- Generate request message for the Google Elevation API --> <Step><Name>AssignElevationParameters</Name></Step> </Request> <Response> <!-- Parse the response message from the Elevation API --> <Step><Name>ParseElevationResponse</Name></Step> <!-- Generate the final JSON-formatted response with JavaScript --> <Step><Name>GenerateResponse</Name></Step> </Response> </Flow> </Flows> <HTTPProxyConnection> <!-- Add a base path to the ProxyEndpoint for URI pattern matching--> <BasePath>/policy-mashup-cookbook</BasePath> <!-- Listen on both HTTP and HTTPS endpoints --> <VirtualHost>default</VirtualHost> <VirtualHost>secure</VirtualHost> </HTTPProxyConnection> <RouteRule name="default"> <!-- Connect ProxyEndpoint to named TargetEndpoint under /targets --> <TargetEndpoint>default</TargetEndpoint> </RouteRule> </ProxyEndpoint>
下面简要介绍了该流程的各个元素。
- <Request> - <Request> 元素由多个 <Step> 元素组成。每个步骤都会调用我们在本主题的其余部分中创建的政策之一。这些政策涉及创建请求消息、发送请求消息和解析响应。学完本主题后,您将了解每项政策的作用。
- <Response> - <Response> 元素还包含 <Steps>。这些步骤还会调用负责处理来自目标端点(Google 高程 API)的最终响应的政策。
- <HttpProxyConnection> - 此元素用于指定应用将如何连接到此 API 代理的相关详细信息,包括 <BasePath>,用于指定如何调用此 API。
- <RouteRule> - 此元素用于指定在处理入站请求消息后立即发生的情况。在这种情况下,TargetEndpoint 称为。 我们将在本主题的后续部分中详细讨论这一重要步骤。
创建政策
以下各部分将讨论构成此政策组合示例的各项政策。
创建第一个 AssignMessage 政策
以下列出的第一个 AssignMessage 政策会创建一个将发送到 Google Geocoding 服务的请求消息。

我们先从政策代码开始,然后更详细地说明其各个元素。在下载的示例中,您可以在文件 doc-samples/policy-mashup-cookbook/apiproxy/policies/GenerateGeocodingRequest.xml 中找到此 XML。
<AssignMessage name="GenerateGeocodingRequest"> <AssignTo createNew="true" type="request">GeocodingRequest</AssignTo> <Set> <QueryParams> <QueryParam name="address">{request.queryparam.postalcode}</QueryParam> <QueryParam name="region">{request.queryparam.country}</QueryParam> <QueryParam name="sensor">false</QueryParam> </QueryParams> <Verb>GET</Verb> </Set> <!-- Set variables for use in the final response --> <AssignVariable> <Name>PostalCode</Name> <Ref>request.queryparam.postalcode</Ref> </AssignVariable> <AssignVariable> <Name>Country</Name> <Ref>request.queryparam.country</Ref> </AssignVariable> </AssignMessage>
下面简要介绍了此政策中的元素。如需详细了解此政策,请参阅分配消息政策。
- <AssignMessage name> - 为此政策指定名称。当在流程中引用政策时,会使用此名称。
- <AssignTo> - 创建一个名为 GeocodingRequest 的命名变量。 此变量封装了将由 ServiceCallout 政策发送到后端的请求对象。
- <QueryParams> - 设置后端 API 调用所需的查询参数。在这种情况下,Geocoding API 需要知道位置信息(以邮政编码表示)和国家/地区 ID。应用用户提供此信息,我们只需在此处提取即可。
sensor参数是 API 所必需的,其值为 true 或 false,我们在此处将其硬编码为 false。 - <Verb> - 在此示例中,我们向 API 发出了一个简单的 GET 请求。
- <AssignVariable> - 这些变量用于存储我们传递给 API 的值。在此示例中,变量将在返回给客户端的响应中稍后被访问。
使用 ServiceCallout 发送请求
政策组合序列中的下一步是创建 ServiceCallout 政策。以下列出的 ServiceCallout 政策会将我们在上一个 AssignMessage 政策中创建的请求对象发送到 Google Geocoding 服务,并将结果保存在名为 GeocodingResponse 的变量中。

与之前一样,我们先来看一下代码。下文将详细说明。如需详细了解此政策,请参阅服务标注政策。在下载的示例中,您可以在文件 doc-samples/policy-mashup-cookbook/apiproxy/policies/ExecuteGeocodingRequest.xml 中找到此 XML。
<ServiceCallout name="ExecuteGeocodingRequest"> <Request variable="GeocodingRequest"/> <Response>GeocodingResponse</Response> <HTTPTargetConnection> <URL>http://maps.googleapis.com/maps/api/geocode/json</URL> </HTTPTargetConnection> </ServiceCallout>
下面简要介绍了此政策的各个要素。
- <ServiceCallout> - 与上一个政策一样,此政策也有一个名称。
- <请求变量> - 这是在 AssignMessage 政策中创建的变量。它封装了发送到后端 API 的请求。
- <Response> - 此元素用于指定存储响应的变量的名称。您会看到,此变量稍后将由 ExtractVariables 政策访问。
- <HTTPTargetConnection> - 指定后端 API 的目标网址。在这种情况下,我们指定 API 返回 JSON 响应。
现在,我们有两个政策,一个政策用于指定使用后端 API(Google 的 Geocoding API)所需的请求信息,另一个政策用于实际向后端 API 发送请求。接下来,我们将处理响应。
使用 ExtractVariables 解析响应
ExtractVariables 政策提供了一种简单机制,用于解析通过 ServiceCallout 政策获得的响应消息中的内容。ExtractVariables 可用于解析 JSON 或 XML,也可用于从 URI 路径、HTTP 标头、查询参数和表单参数中提取内容。

下面列出了 ExtractVariables 政策。如需详细了解此政策,请参阅提取变量政策。在下载的示例中,您可以在文件 doc-samples/policy-mashup-cookbook/apiproxy/policies/ParseGeocodingResponse.xml 中找到此 XML。
<ExtractVariables name="ParseGeocodingResponse"> <Source>GeocodingResponse</Source> <VariablePrefix>geocoderesponse</VariablePrefix> <JSONPayload> <Variable name="latitude"> <JSONPath>$.results[0].geometry.location.lat</JSONPath> </Variable> <Variable name="longitude"> <JSONPath>$.results[0].geometry.location.lng</JSONPath> </Variable> </JSONPayload> </ExtractVariables>
ExtractVariable 政策的关键要素包括:
- <ExtractVariables name> - 同样,政策名称用于在流程中使用政策时引用政策。
- <Source> - 指定我们在 ServiceCallout 政策中创建的响应变量。这是相应政策从中提取数据的变量。
- <VariablePrefix> - 变量前缀用于为此政策中创建的其他变量指定命名空间。前缀可以是任何名称,但不能是 Edge 的预定义变量所定义的预留名称。
- <JSONPayload> - 此元素会检索我们感兴趣的响应数据,并将其放入已命名的变量中。事实上,Geocoding API 返回的信息远不止纬度和经度。不过,对于此示例,我们只需要这些值。您可以在 API 的文档中查看 Geocoding API 返回的 JSON 的完整呈现效果。geometry.location.lat 和 geometry.location.lng 的值只是返回的 JSON 对象中的众多字段中的两个。
虽然可能不太明显,但重要的是要看到 ExtractVariables 会生成两个变量,这两个变量的名称由变量前缀 (geocoderesponse) 和政策中指定的实际变量名称组成。这些变量存储在 API 代理中,并且可供代理流中的其他政策使用,这一点您稍后会看到。变量如下:
- geocoderesponse.latitude
- geocoderesponse.longitude
现在,大部分工作都已完成。我们创建了一个由三项政策组成的复合政策,该政策会生成请求、调用后端 API 并解析返回的 JSON 数据。在最后几个步骤中,我们将此流程部分的数据馈送到另一个 AssignMessage 政策,调用第二个后端 API(Google Elevation API),并将混合数据返回给应用开发者。
使用 AssignMessage 生成第二个请求
以下 AssignMessage 政策使用我们存储的从第一个后端(Google Geocoding)返回的变量,并将它们插入到发往第二个 API(Google Elevation)的请求中。如前所述,这些变量是 geocoderesponse.latitude 和 geocoderesponse.longitude。
在下载的示例中,您可以在文件 doc-samples/policy-mashup-cookbook/apiproxy/policies/AssignElevationParameters.xml 中找到此 XML。
<AssignMessage name="AssignElevationParameters">
<Remove>
<QueryParams>
<QueryParam name="country"/>
<QueryParam name="postalcode"/>
</QueryParams>
</Remove>
<Set>
<QueryParams>
<QueryParam name="locations">{geocoderesponse.latitude},{geocoderesponse.longitude}</QueryParam>
<QueryParam name="sensor">false</QueryParam>
</QueryParams>
</Set>
</AssignMessage>如果您查看 Google Elevation API,会发现它需要两个查询参数。
第一个称为 locations,其值为纬度和经度(以逗号分隔的值)。另一个形参是 sensor,它是必需的,必须为 true 或 false。此时需要注意的最重要的一点是,我们在此处创建的请求消息不需要 ServiceCallout。我们无需在此阶段通过 ServiceCallout 调用第二个 API,因为我们可以通过代理的 TargetEndpoint 调用后端 API。仔细想想,我们已经拥有调用 Google Elevations API 所需的所有数据。在此步骤中生成的请求消息不需要 ServiceCallout,因为它是为主要请求流水线生成的请求,因此 ProxyEndpoint 会按照为此 API 代理配置的 RouteRule 将其简单地转发到 TargetEndpoint。TargetEndpoint 管理与远程 API 的连接。(请注意,高程 API 的网址是在 TargetEndpoint 的 HTTPConnection 中定义的。如果您想了解详情,请参阅 Elevation API 文档。之前存储的 QueryParams(即 country 和 postalcode)不再需要,因此我们在此处将其移除。
短暂暂停:回到工作流
此时,您可能会想知道为什么我们不创建另一个 ServiceCallout 政策。毕竟,我们创建了另一条消息。如何将该消息发送到目标 Google 高程 API?答案位于流程的 <RouteRule> 元素中。<RouteRule> 用于指定在执行完流程的 <Request> 部分后,如何处理所有剩余的请求消息。此 <RouteRule> 指定的 TargetEndpoint 会告知 API 代理将消息传递到 http://maps.googleapis.com/maps/api/elevation/xml。
如果您下载了示例 API 代理,则可以在文件 doc-samples/policy-mashup-cookbook/apiproxy/targets/default.xml 中找到 TargetProxy XML。
<TargetEndpoint name="default"> <HTTPTargetConnection> <!-- This is where we define the target. For this sample we just use a simple URL. --> <URL>http://maps.googleapis.com/maps/api/elevation/xml</URL> </HTTPTargetConnection> </TargetEndpoint>
现在,我们只需要处理 Google 高程 API 的响应,就完成了。
将响应从 XML 转换为 JSON
在此示例中,Google 高程 API 的响应以 XML 格式返回。为了“额外加分”,我们再向复合政策添加一项政策,以将响应从 XML 转换为 JSON。
此示例使用名为 GenerateResponse 的 JavaScript 政策(其中包含 JavaScript 代码的资源文件)来执行转换。GenerateResponse 政策的定义如下所示:
<Javascript name="GenerateResponse" timeout="10000"> <ResourceURL>jsc://GenerateResponse.js</ResourceURL> </Javascript>
GenerateResponse.js 资源文件包含用于执行转换的 JavaScript。您可以在文件 doc-samples/policy-mashup-cookbook/apiproxy/resources/JSC/GenerateResponse.js 中查看该代码。
Apigee 还提供了一项开箱即用的政策 XMLToJSON,用于将 XML 转换为 JSON。您可以修改 ProxyEndpoint 以改用以下 xmltojson 政策。
<XMLToJSON name="xmltojson"> <Options> </Options> <OutputVariable>response</OutputVariable> <Source>response</Source> </XMLToJSON>
测试示例
如果您尚未这样做,请尝试下载、部署和运行 policy-mashup-cookbook 示例,您可以在 Apigee Edge 示例代码库 GitHub 中的 doc-samples 文件夹中找到该示例。只需按照 policy-mashup-cookbook 文件夹中的 README 文件中的说明操作即可。或者,按照此处的简要说明操作:使用示例 API 代理。
总而言之,您可以按如下方式调用复合 API。将 {myorg} 替换为您的组织名称:
$ curl "http://{myorg}-test.apigee.net/policy-mashup-cookbook?country=us&postalcode=08008"
响应包含应用最终用户提供的邮政编码中心的地理编码位置,以及该地理编码位置的海拔高度。数据从两个后端 API 中检索,通过附加到 API 代理的政策进行混搭,然后以单个响应的形式返回给客户端。
{ "country":"us", "postalcode":"08008", "elevation":{ "meters":0.5045232, "feet":1.6552599030345978 }, "location":{ "latitude":39.75007129999999, "longitude":-74.1357407 } }
摘要
此食谱主题介绍了如何使用政策组合模式来混搭来自多个后端来源的数据。政策组合是 API 代理开发中常用的一种模式,用于为 API 添加创新功能。