使用政策构成

您正在查看的是 Apigee Edge 文档。
转到 Apigee X 文档
信息

在本主题中,您将学习如何使用政策组合创建混搭程序。政策组合是一种 Apigee 代理模式,可让您使用政策将多个后端目标的结果合并到单个响应中。

如需大致了解政策组合,请参阅 API 代理实战宝典模式中的“政策组合模式”。

下载并试用示例代码

关于此食谱集示例

本实战宝典示例展示了一个名为“政策组合”的 API 代理模式。此模式提供了一种(还有多种)混搭来自多个后端来源的数据的方法。概括来说,本主题演示了如何将政策组合起来并链接在一起来生成期望的结果。如需大致了解此模式和其他相关模式,请参阅 API 代理实战宝典模式

此处讨论的示例使用政策组合将来自以下两个单独的公共 API 的数据进行混搭:

  • Google Geocoding API:此 API 可将地址(例如“1600 Amphitheatre Parkway, Mountain View, CA”)转换为地理坐标(例如纬度 37.423021 和经度 -122.083739)。
  • Google Elevation 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 代理实战宝典模式中的“政策组合模式”。

在浏览本实战宝典示例之前,您还应熟悉以下基本概念:

  • 什么是政策以及如何将它们附加到代理。如需查看有关政策的详细介绍,请参阅什么是政策?
  • API 代理流的结构(如配置流中所述)。通过流,您可以指定 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>

下面是 flow 的元素的摘要。

  • <Request> - <Request> 元素包含几个 <Step> 元素。每个步骤都会调用我们在本主题的其余部分中创建的一项政策。这些政策涉及创建请求消息、发送请求消息以及解析响应。在本主题结束时,您将了解各项政策的作用。
  • <Response> - <Response> 元素还包含 <Steps>。这些步骤还会调用负责处理来自目标端点(Google Elevation API)的最终响应的政策。
  • <HttpProxyConnection> - 此元素指定有关应用如何连接到此 API 代理的详细信息,包括指定如何调用此 API 的 <BasePath>。
  • <RouteRule> - 此元素指定处理完入站请求消息后应立即执行的操作。在本例中,系统调用 TargetEndpoint。 我们稍后会在本主题中详细讨论这一重要步骤。

创建政策

以下部分讨论了此政策组合示例中包含的每项政策。

创建第一个 assignMessage 政策

下文列出的第一项 AssignMessage 政策会创建一条将发送给 Google 地理编码服务的请求消息。

我们先从政策代码开始,然后更详细地说明其元素。在示例下载中,您可以在文件 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 表示。这类信息由应用用户提供,我们仅在此处提取。该 API 需要 sensor 参数,可以是 true 或 false,我们只需在此处将其硬编码为 false 即可。
  • <Verb> - 在此示例中,我们将向 API 发出简单的 GET 请求。
  • <AssignVariable> - 这些变量存储我们传递给 API 的值。在此示例中,稍后会在返回给客户端的响应中访问这些变量。

使用 ServiceCallout 发送请求

政策组合序列中的下一步是创建 ServiceCallout 政策。下面列出的 ServiceCallout 政策会将我们在之前的 assignMessage 政策中创建的请求对象发送给 Google 地理编码服务,并将结果保存在一个名为 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> - 与前面的政策一样,此政策有一个名称。
  • <Request variable> - 这是在 AssignmentMessage 政策中创建的变量。它会封装发送到后端 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 返回的信息比纬度和经度多得多。但是,此示例只需要这些值。如需查看 Geocoding API 返回的 JSON 的完整呈现,请参阅 API 文档。Geos.location.lat 和 geometry.location.lng 的值只是返回的 JSON 对象中众多字段的两个。

此举可能看似不明显,但请务必注意,ExtractVariables 会生成两个名称,这些变量的名称由变量前缀(地理编码响应)和政策中指定的实际变量名称组成。这些变量存储在 API 代理中,将可供代理流程中的其他政策使用,如您所见。变量包括:

  • geocoderesponse.latitude
  • geocoderesponse.longitude

大部分工作现已完成。我们创建了一个由三项政策的组合,构成请求、调用后端 API 并解析返回的 JSON 数据。在最后的步骤中,我们会将来自流程的这一部分的数据馈送到另一个 assignMessage 政策,调用第二个后端 API (Google Elevation API),并将混搭后的数据返回给应用开发者。

使用 assignMessage 生成第二个请求

以下 assignMessage 政策使用从我们存储的第一个后端(Google 地理编码)返回的变量,并将其插入到发往第二个 API(Google Elevation)的请求中。如前所述,这些变量是 Geocodingresponse.latitude 和 Geocodingresponse.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(countrypostalcode)已不再需要,因此我们在此处将其移除。

短暂暂停:返回流程

此时,您可能想知道为什么我们没有创建另一个 ServiceCallout 政策。毕竟,我们创建了另一条消息。该消息是如何发送到目标(即 Google Elevation 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 Elevation API 的响应,就大功告成了。

将响应从 XML 转换为 JSON

在此示例中,来自 Google Elevation 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 中添加广告素材功能。