使用流变量

本页面适用于 ApigeeApigee Hybrid

查看 Apigee Edge 文档。

流变量是可以在政策或实用程序(例如调试工具)中访问的对象。通过这些变量,您可以维护与 Apigee 处理的 API 事务关联的状态。

什么是流变量?

API 代理流的环境中存在流变量,可用来跟踪 API 事务中的状态,就像跟踪软件程序中已命名的变量状态一样。流变量存储如下信息:

  • 从发出请求的应用发送的 IP 地址、标头、网址路径和载荷
  • 系统信息,例如 Apigee 收到请求的日期和时间
  • 政策执行时派生的数据。例如,在验证 OAuth 令牌的政策执行后,Apigee 会创建流变量来保存请求应用的名称等信息。
  • 来自目标系统的响应的相关信息

一些变量内置在 Apigee 中,并且在接收 API 请求时自动填充。您可以在整个 API 事务中找到这些变量。您还可以使用 AssignMessage 政策等政策创建自己的自定义变量,或在 JavaScript 和 Java 代码中创建。

如您所见,变量的范围也有限制,可在哪些位置访问变量取决于变量在 API 代理流中的创建时间。通常,在创建变量后,它可供稍后在 API 事务流中执行的所有政策和代码使用。

如何使用流变量?

政策条件流中使用了流变量:

  • 政策可以从流变量中检索状态,并使用流变量来完成工作。

    例如,VerifyJWT 政策可以从流变量检索要验证的令牌,然后验证令牌。再举一例,JavaScript 政策可以检索流变量并对这些变量中包含的数据进行编码。

  • 条件流可以引用流变量,以通过 Apigee 定向 API 流,这与 switch 语句在编程中的工作方式类似。

    例如,用于返回故障的政策仅在设置了特定流变量时执行。

让我们通过几个示例来了解如何在这些上下文中使用变量。

政策中的流变量

一些政策将流变量作为输入。

例如,以下 AssignMessage 政策采用流变量 client.ip 的值,并将其放在名为 My-Client-IP 的请求标头中。如果已在请求流中添加此政策,则此政策会设置传递给后端目标的标头。如果已在响应流上设置此政策,则系统会将标头发送回客户端应用。

<AssignMessage name="set-ip-in-header">
    <AssignTo createNew="false" transport="http" type="request">request</AssignTo>
    <Set>
        <Headers>
            <Header name="My-Client-IP">{client.ip}</Header>
        </Headers>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

在另一个示例中,当配额政策执行时,系统会使用与政策相关的值填充多个流变量。其中一个变量名为 ratelimit.my-quota-policy.used.count(其中,my-quota-policy 是您感兴趣的配额政策的名称)。

您可以稍后执行条件流,即“如果当前配额计数低于上限值的 50% 且发生在上午 9 点到下午 5 点之间,则系统会强制执行不同的配额。”此条件可能依赖于当前配额计数的值和名为 system.time 的流变量(一种内置 Apigee 变量)。

条件流中的流变量

条件流可用来评估流变量并可让代理动态运行。条件通常用于更改流的行为、步骤和路由规则。

下面是一个条件流,用来评估代理流步骤中变量 request.verb 的值。在这种情况下,如果请求动词是 POST,则会执行 VerifyAPIKey 政策。这是 API 代理配置中使用的一种常见模式。

<PreFlow name="PreFlow">
    <Request>
        <Step>
            <Condition>request.verb equals "POST"</Condition>
            <Name>VerifyApiKey</Name>
        </Step>
    </Request>
</PreFlow>

现在,您可能想知道 request.verbclient.ipsystem.time 等变量来自哪里?何时实例化这些变量并使用值进行填充?如需帮助您了解变量的创建时间以及何时可供您使用,请参阅直观呈现 API 代理流

使用 JavaScript 政策调用的 JavaScript 代码中的流变量

借助 JavaScript 政策,您可以在 API 代理流的环境中执行 JavaScript 代码。此政策执行的 JavaScript 使用 Apigee JavaScript 对象模型,该模型可让您的自定义代码访问与执行该代码所在的 API 代理流相关的请求、响应和上下文对象。例如,此代码使用从流变量 target.name 获取的值设置响应标头。

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

使用 JavaScript 读取和设置变量的技术与使用 AssignMessage 政策执行的工作(如上所示)类似。这只是在 Apigee 上完成相同操作的另一种方法。需要记住的关键一点是,通过 JavaScript 政策执行的 JavaScript 有权访问 API 代理流中存在且位于范围内的所有流变量。

直观呈现 API 代理流

要了解流变量的范围,请务必了解或直观呈现消息通过 API 代理的方式。API 代理包含一系列以流形式整理的消息处理步骤。在代理流的每个步骤中,代理都会评估步骤可用的信息并决定后续操作。在此过程中,代理可以执行政策代码或执行条件拆分

下图演示了这一系列流。请注意,这些流由四个主要片段组成:ProxyEndpoint 请求、TargetEndpoint 请求、TargetEndpoint 响应和 ProxyEndpoint 响应

HTTP 客户端请求通过 API 代理发送到 HTTP 服务,然后响应会通过 API 代理返回给客户端。

随着我们完成本主题的其余部分来开始探索流变量时,请记住这种流结构。

变量范围与代理流有何关联

如上文所述,只要您可以直观呈现消息如何流经代理,就可以立即开始了解变量的范围。范围指的是在首次实例化某个变量时代理流生命周期中的时间点。

例如,如果您将某个政策附加到 ProxyEndpoint 请求片段,则该政策将无法访问范围限于 TargetEndpoint 请求片段的任何变量。这是因为流的 TargetEndpoint 请求片段尚未执行,因此 API 代理还没有机会填充该范围内的变量。

下表列出了完整的变量范围集,并指明在代理流中变量何时可用。

变量范围 这些变量的填充位置
代理请求 ProxyEndpoint 请求片段
目标请求 TargetEndpoint 请求片段
目标响应 TargetEndpoint 响应片段
代理响应 ProxyEndpoint 响应片段
随时提供 代理收到请求后立即执行。这些变量在整个代理流生命周期内都可用。

例如,有一个名为 client.ip 的内置 Apigee 变量。此变量具有代理请求范围。其中会自动填充调用该代理的客户端的 IP 地址。当某个请求首次进入 ProxyEndpoint 时,系统会填充该变量,且变量在代理流的整个生命周期内都可用。

还有一个名为 target.url 的内置变量。此变量的范围为目标请求。在 TargetEndpoint 请求片段中,该变量中将填充传送给后端目标的请求网址。如果您尝试访问 ProxyEndpoint 请求片段中的 target.url,您将收到 NULL 值。如果您尝试在此变量限定范围之前先设置此变量,则该代理不会执行任何操作,即不会生成错误,也不会设置变量。

下面是一个简单的示例,演示了如何考虑变量范围。假设您要复制请求对象的全部内容(标头、参数、正文),并将其分配给要发送回调用应用的响应载荷。您可以使用 AssignMessage 政策来完成此任务。政策代码如下所示:

<AssignMessage name="CopyRequestToResponse">
    <AssignTo type="response" createNew="false">response</AssignTo>
    <Copy source="request"/>
</AssignMessage>

此政策只会复制 request 对象,并将其分配给 response 对象。但此政策在代理流中应放置在哪些位置?答案是必须将它置于 TargetEndpoint 响应中,因为响应变量的范围为“目标响应”。

引用流变量

Apigee 中的所有内置变量均遵循点表示法命名惯例。此惯例可让您更轻松地确定变量的用途。例如 system.time.hourrequest.content

Apigee 保留各种前缀以适当地整理相关变量。这些前缀包括:

  • request
  • response
  • system
  • target

如需引用政策中的变量,请用大括号括住该变量。例如,以下 AssignMessage 政策采用变量 client.ip 的值,并将其放在名为 Client-IP 的请求标头中。

<AssignMessage name="set-ip-in-header">
    <AssignTo createNew="false" transport="http" type="request">request</AssignTo>
    <Set>
        <Headers>
            <Header name="Client-IP">{client.ip}</Header>
        </Headers>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

在条件流中,不需要使用大括号。以下条件示例将评估变量 request.header.accept

<Step>
    <Condition>request.header.accept = "application/json"</Condition>
    <Name>XMLToJSON</Name>
</Step>

您还可以引用 JavaScript 和 Java 代码中的流变量。有关详情,请参阅:

流变量的数据类型

流变量的每个属性都具有明确定义的数据类型,例如字符串、长整数、整数、布尔值或集合。您可以找到流变量参考文档中列出的数据类型。对于政策创建的变量,请参阅具体的政策参考主题以了解数据类型信息。

您手动创建的变量采用创建它们时指定的类型,具体取决于允许的值类型。

在政策中使用流变量

许多政策会在正常执行过程中创建流变量。政策参考文档记录了所有这些政策专用变量。

在使用代理和政策时,请务必查看政策参考文档,以了解创建的变量以及变量的用途。例如,配额政策会创建一组变量,其中包含配额计数和限额以及到期时间等相关信息。

某些政策变量对于调试非常有用。例如,您可以使用 调试工具来查看在代理流中的特定实例上设置了哪些变量。

借助 ExtractVariables 政策,您可以使用从消息中提取的数据填充自定义变量。您可以提取查询参数、标头和其他数据。例如,您可以使用模式解析请求和响应消息,以从消息中提取特定数据。

在以下示例中,ExtractVariables 政策会解析响应消息并存储从响应中获取的特定数据。该政策会创建两个自定义变量(geocoderesponse.latitudegeocoderesponse.longitude)并为其赋值。

<ExtractVariables name="ParseGeocodingResponse">
  <Source>response</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>

同样,请注意许多政策会自动创建变量。您可以在代理流上下文中访问这些变量,其具体记录在每个政策主题下的政策参考文档中。

在 JavaScript 代码中使用流变量

您可以在 API 代理的环境中执行的 JavaScript 代码中直接访问和设置变量。通过 Apigee JavaScript 对象模型,在 Apigee 上执行的 JavaScript 可以直接访问代理流变量。

要访问 JavaScript 代码中的变量,请针对以下任何对象调用 getter/setter 方法:

  • context
  • proxyRequest
  • proxyResponse
  • targetRequest
  • targetResponse

如您所见,这些对象引用映射到代理流模型中熟悉的片段,如前面的直观呈现 API 代理流所述。

context 对象对应于“全局”可用变量,例如系统变量。例如,您可以对 context 对象调用 getVariable() 以获取当前年份:

var year = context.getVariable('system.time.year');

同样,您可以调用 setVariable() 来设置自定义变量的值或任意开箱即用的可写变量的值。在这里,我们将创建一个名为 organization.name.myorg 的自定义变量并为其赋值。

var org = context.setVariable('organization.name.myorg', value);

由于此变量是使用 context 对象创建的,因此它可用于所有流片段(实质上类似于创建全局变量)。

您还可以在使用 JavaCallout 政策执行的 Java 代码中获取或设置代理流变量。

注意事项

以下是有关流变量的几个重要注意事项:

  • 某些“开箱即用”的变量由代理本身自动实例化并填充。这些变量记录在流变量参考文档中。
  • 您可以创建可在代理流中使用的自定义变量。可以使用 AssignMessage 政策JavaScript 政策等政策创建变量。
  • 变量具有范围。例如,当第一个代理收到来自应用的请求时,系统会自动填充某些变量。其他变量会在代理的响应流片段中进行填充。这些响应变量在响应片段执行之前保持未定义状态。
  • 政策执行时,它们可以创建和填充政策专用变量。每项政策的文档都会列出所有这些相关的政策专用变量。
  • 条件流通常用于评估一个或多个变量。如果您想创建条件流,则需要了解变量。
  • 许多政策都使用变量作为输入或输出。一个政策创建的变量随后可能被另一个政策使用。

相关主题

  • 流变量参考文档中列出了自动填充 API 代理的所有变量。该文档中还列出了每个变量的类型和范围。
  • 如需了解特定政策填充哪些变量,请参阅该政策对应的参考主题。例如,请参阅配额政策参考文档中的流变量