包含流变量的条件

<ph type="x-smartling-placeholder"></ph> 您正在查看 Apigee Edge 文档。
转到 Apigee X 文档
信息

条件语句是所有编程语言中的常用控制结构。与编程语言一样,API 代理配置支持针对流、政策、步骤和 RouteRule 的条件语句。通过定义条件语句,可为 API 定义动态行为。此动态行为可让您执行一些操作,比如仅针对移动设备将 XML 转换为 JSON,或根据请求消息的内容类型或 HTTP 谓词路由到后端网址。

本主题介绍如何在运行时使用条件动态应用 API 管理功能,而无需编写任何代码。

配置条件语句

条件行为通过组合使用条件和变量在 API 代理中实现。使用 Condition 元素创建条件语句。以下是空条件:

<Condition></Condition>

如需创建条件语句,请添加条件运算符和变量以创建以下结构:

<Condition>{variable.name}{operator}{"value"}</Condition>

支持的条件运算符包括 =(等于)、!=(不等于)和 >(大于)。为方便阅读,您也可以将条件写成以下文本:equalsnotequalsgreaterthan

使用 URI 路径时,可以使用 ~/MatchesPath。还可以通过 ^ 运算符匹配 JavaRegex 正则表达式。

条件用于定义到后端 API 资源的 API 代理条件流(请参阅创建到后端 API 资源的条件流)。如需查看条件的完整列表,请参阅条件参考

变量

条件通过求变量的值来完成工作。变量是由 API 代理或 API 代理配置本身的属性执行的 HTTP 事务的属性。每当 API 代理收到来自应用的请求时,Apigee Edge 都会填充 一长串变量,与系统时间、应用的网络等因素相关联 信息、邮件上的 HTTP 标头、API 代理配置、政策执行等。 这会创建一个内容丰富的上下文,可供您用来设置条件语句。

变量始终使用虚线表示法。例如,请求消息上的 HTTP 标头将作为名为 request.header.{header_name} 的变量提供。因此,要对 Content-type 标头求值,您可以使用变量 request.header.Content-type。例如,request.header.Content-type = "application/json" 表示请求的内容类型应为 JSON。

假设您需要创建一个条件语句,作用是使得仅当请求消息是 GET 时,系统才会强制执行某个政策。如需创建用于对请求的 HTTP 谓词求值的条件,请创建以下条件语句。此条件中的变量为 request.verb。此变量的值为 GET。运算符为 =

<Condition>request.verb = "GET"</Condition>
您还可以使用:
<Condition>request.verb equals "GET"</Condition>

Edge 使用此类语句来评估条件。如果与请求关联的 HTTP 谓词是 GET,则以上示例的求值结果为 true。如果与请求关联的 HTTP 谓词是 POST,则语句的求值结果为 false。

如需启用动态行为,可以将条件附加到流、步骤和 RouteRule。

将条件附加到流时,将创建“条件流”。条件流仅在条件为 true 时执行。您可以根据需要将任意数量的政策附加到条件流中。借助条件流,您可为满足特定条件的请求或响应消息创建非常专业的处理规则。

例如,如需创建仅当请求谓词为 GET 时执行的流:

<Flows>
  <Flow name="ExecuteForGETs">
  <Condition>request.verb="GET"</Condition>
  </Flow>
</Flows>

如需为 GET 创建一个流,为 POST 创建另一个流:

<Flows>
  <Flow name="ExecuteForGETs">
  <Condition>request.verb="GET"</Condition>
  </Flow>
  <Flow name="ExecuteForPOSTs">
  <Condition>request.verb="POST"</Condition>
  </Flow>
</Flows>

如下例所示,您可以将条件应用于政策步骤本身。只有在满足请求消息为 POST 条件时,以下条件才会导致强制执行 VerifyApiKey 政策。

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

在定义此类条件流后,您就可以将政策附加到这些条件流,使 API 代理针对 GET 请求强制执行一组政策,为 POST 请求强制执行另一组政策。

如需了解全面的参考信息,请参阅以下资源:

示例 1

以下示例展示了在 ProxyEndpoint 响应流中配置的单个条件流 Convert-for-devices。将条件作为元素添加到条件应用于的实体。在此示例中,条件是流的一个组件。因此,只要语句的求值结果为 true,就会执行该流。

<Flows>
  <Flow name="Convert-for-devices">
  <Condition>(request.header.User-Agent = "Mozilla")</Condition>
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

对于从应用接收到的每个请求,Edge 会将所有 HTTP 标头的值存储为 变量。如果请求包含名为 User-Agent 的 HTTP 标头,则该标头及其值将存储为名为 request.header.User-Agent 的变量。

根据上面的 ProxyEndpoint 配置,Edge 会检查 request.header.User-Agent 变量,用于查看条件的求值结果是否为 true。

如果条件的求值结果为 true,即变量 request.header.User-Agent 的值等于 Mozilla,则会执行条件流,并强制执行名为 ConvertToJSON 的 XMLtoJSON 政策。否则,系统不会执行该流,并会向发出请求的应用返回未经修改的 XML 响应(采用 XML 格式)。

示例 2

让我们用一个具体的示例进行说明。在该示例中,您需要将响应消息从 XML 转换为 JSON - 但仅适用于移动设备。首先,创建政策,用于将 Weather API 的 XML 格式的响应转换为 JSON:

<XMLToJSON name="ConvertToJSON">
  <Options>
  </Options>
  <OutputVariable>response</OutputVariable>
  <Source>response</Source>
</XMLToJSON>

上述政策配置会指示 API 代理获取响应消息,使用默认设置从 XML 转换为 JSON,然后将结果写入新的响应消息。(如果要将请求消息从 XML 转换为 JSON,则只需将这两个值都设置为 request 即可。)

因为您想要将响应从 XML 转换为 JSON,所以您需要配置条件响应流以执行转换。例如,如需将所有响应先从 XML 转换为 JSON 格式再返回给客户端应用,请配置以下 ProxyEndpoint 响应流。

<Flows>
  <Flow name="Convert-for-devices">
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

使用标准请求调用 API 时,响应将采用 JSON 格式。

不过,您的目标是仅当发出请求的客户端是移动设备时,才能将天气报告转换为 JSON 格式。如需实现此类动态行为,您必须向流添加条件语句。

测试条件流

在此示例请求中,HTTP User-Agent 标头设置为 Mozilla,使得条件语句的求值结果为 true 并执行条件流 Convert-for-devices

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

或者,当 Python 可用时进行整齐打印:

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282 | python -mjson.tool

示例响应:

. . .

"yweather_forecast": [
         {
              "code": "11",
              "date": "12 Dec 2012",
              "day": "Wed",
              "high": "55",
              "low": "36",
              "text": "Showers"
          },
          {
              "code": "32",
              "date": "13 Dec 2012",
              "day": "Thu",
              "high": "56",
              "low": "38",
              "text": "Sunny"
          }
      ]
  }

. . .

如果您提交的请求缺少 User-Agent 标头,或者其值不是 Mozilla,则会产生 XML 格式响应。

$ curl http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

系统会返回未经修改的 XML 响应。

示例响应:

<yweather:forecast day="Wed" date="12 Dec 2012" low="36" high="55" text="Showers" code="11" /> <yweather:forecast day="Thu" date="13 Dec 2012" low="38" high="56" text="Sunny" code="32" />

模式匹配

本部分介绍如何在 Apigee 流中使用与条件匹配的模式。

运算符

本部分介绍如何在条件语句中使用以下模式匹配运算符:

Matches

我们先来看看 Matches 或 ~ 条件运算符。这两个运算符是相同的,但英语版本的 Matches 可读性更好。

摘要:Matches 运算符可提供两种可能性。您可以逐字匹配字符串,也可以使用 * 执行通配符匹配。正如您所预期那样,通配符与零个或多个字符匹配。下面我们来看看具体操作方式。

以下 XML 展示了步骤条件。当条件的求值结果为 true 时,将会执行 SomePolicy 政策。在此示例中,我们测试了 proxy.pathsuffix 变量, Edge 中的内置变量,用于存储请求的路径后缀。不过,请注意,您可以测试包含字符串的任何流变量的值。因此,在本示例中,如果传入请求的基本路径为 /animals,且请求为 /animals/cat,则路径后缀为字面量字符串“/cat”。

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix Matches "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

问题:什么样的代理路径后缀会导致执行 SomePolicy?只有一个可能。

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?是,因为代理路径后缀与“/cat”完全匹配。如果后缀为 /bat/dog/ 或任何其他值,它将不会执行。

现在,看看以下条件语句,我们在其中使用了通配符“*”:

<Condition>(proxy.pathsuffix Matches "/*at")</Condition>

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?是,因为通配符与任何字符匹配,“"/cat”是匹配项。

API 调用

GET http://artomatic-test.apigee.net/matchtest/bat

该政策是否执行?是,因为通配符匹配任何字符,"/bat" 是匹配项。

API 调用

GET http://artomatic-test.apigee.net/matchtest/owl

该政策是否执行?当然不执行,虽然通配符与“o”匹配,但字母“wl”不匹配。

现在,将通配符移到后缀的末尾:

<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?是,因为通配符与零个或多个任意字符匹配。

API 调用

GET http://artomatic-test.apigee.net/matchtest/bat

该政策是否执行?否,“/bat”不是匹配项。

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat123

该政策是否执行?是,通配符可以匹配零个或多个任意字符,因此“123”会生成一个匹配项。

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat/bird/mouse

该政策是否执行?是,因为通配符可以匹配零个或多个任意字符,因此“/bird/mouse”会产生一个匹配项。请注意,类似这样的表达式会让您陷入麻烦,因为它会匹配字面量字符后的所有内容!

问题:Matches 运算符是否区分大小写?

是。假设您的条件如下:

<Condition>(proxy.pathsuffix Matches "/*At")</Condition>

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?否,通配符可匹配任何字母(不区分大小写),但小写“a”与大写“A”不匹配。

API 调用

GET http://artomatic-test.apigee.net/matchtest/bAt

该政策是否执行?是,大小写匹配。

问题:如何使用 Matches 运算符将字符转义?

使用百分比“%”字符来将保留字符转义。例如:

<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?否,Matches 运算符寻找的是字面量字符串“c*at”。

API 调用

GET http://artomatic-test.apigee.net/matchtest/c*at

问题:政策是否执行?

是,虽然此路径有点异常,但是它匹配。

JavaRegex

如您所见,“Matches”运算符非常适合于简单的情形。不过,您可以使用其他运算符,即“JavaRegex”或“~~”运算符。这两个运算符是相同的,但 JavaRegex 可读性更好。之所以称之为 JavaRegex,是因为它允许使用正则表达式 模式匹配,并且 Edge 遵循与 java.util.regex 中的类相同的规则 软件包。JavaRegex 运算符的工作方式与 Matches 运算符大不相同,因此,务必不要混淆这两者!

摘要:通过“JavaRegex”运算符,您可以在条件语句中使用正则表达式语法。

以下代码显示了步骤条件。如果条件满足 计算结果为 true。在此示例中,我们测试了 proxy.pathsuffix 变量, 变量,用于存储请求的路径后缀。如果传入请求的基本路径为 /animals,且请求为 /animals/cat,则路径后缀为字面量字符串“/cat”。

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

问题:什么样的代理路径后缀会导致执行 SomePolicy?与“匹配”运算符一样,在此示例中,只有一个可能。

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?是,因为代理路径后缀与“/cat”完全匹配。如果后缀为 /bat/dog 或任何其他值,该政策将不会执行。

现在,我们使用“*”限定符创建正则表达式。此限定符与一个或多个前面的字符匹配。

<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?否!“*”限定符与零个或零个以上的前面的字符(即“c”)匹配。

API 调用

GET http://artomatic-test.apigee.net/matchtest/ccccct

该政策是否执行?是,因为通配符与零个或零个以上前面的字符匹配。

接下来,我们使用“?”限定符,它只会匹配前面的字符一次,或者根本不匹配。

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?是。“?”限定符与零个或一个前面的字符匹配,即“a”。

API 调用

GET http://artomatic-test.apigee.net/matchtest/ct

该政策是否执行?是。“?”限定符与一个或零个前面的字符匹配,在本示例中,不存在“a”字符,因此条件的求值结果为 true。

API 调用

GET http://artomatic-test.apigee.net/matchtest/caat

该政策是否执行?否。“?”限定符与一个前面的字符(即“a”)匹配。

接下来,我们使用正则表达式的“[abc]”或“分组”样式。它与字符“a”、“b”或“c”匹配。

<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at")</Condition>

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?是。我们在这里使用正则表达式,“[cbr]”表达式匹配“c”、“b”或“r”。这些调用也匹配:

GET http://artomatic-test.apigee.net/matchtest/bat

GET http://artomatic-test.apigee.net/matchtest/rat

但这不是一个匹配项:

GET http://artomatic-test.apigee.net/matchtest/mat

问题:JavaRegex 运算符是否区分大小写?

可以。假设您的条件如下:

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat

该政策是否执行?是,正则表达式与零个或一个前面的字符(即“a”)匹配。

API 调用

GET http://artomatic-test.apigee.net/matchtest/cAt

问题:该政策是否执行?

否,因为大写字母“A”与小写字母“a”不匹配。

MatchesPath

您也可按照以下方式指定 MatchesPath 运算符:“~/”。这有点像 Matches (~) 和 JavaRegex (~~) 运算符。但 MatchesPath 完全不同。

请记住,此运算符将路径视为一系列部分。因此,如果路径为 /animals/cats/wild,那么可以将路径视为由“/animals”、“/cats”和“/wild”等部分组成。

MatchesPath 运算符允许您使用两个通配符表示法:单星号 (*) 和双星号 (**)。单星号与一个路径元素相匹配。双星号与一个或多个路径元素相匹配。

下面我们来看一个示例。在此示例中,我们测试了变量 proxy.pathsuffix。 Edge 中的内置变量,用于存储请求的路径后缀。不过,请注意,您可以测试包含字符串的任何流变量的值。

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

问题:什么样的代理路径后缀会导致执行 SomePolicy?

API 调用

GET http://artomatic-test.apigee.net/matchtest/animals

问题:该政策是否执行?

否,因为条件需要在“/animals”后面使用另一个路径元素,如通过“/*”指定的路径元素。

API 调用

GET http://artomatic-test.apigee.net/matchtest/animals/

该政策是否执行?是,该路径还有另一个路径元素(“/animals/”后面的部分),但它是空的。

API 调用

GET http://artomatic-test.apigee.net/matchtest/animals/cats

该政策是否执行?是,因为路径在“/animals”后面明确包含一个元素(“/cats”)。

API 调用

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

问题:该政策是否执行?

否,因为单个星号仅匹配一个路径元素,并且此 API 在“/animals”后面有多个元素。

现在我们使用双星号:

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

问题:什么样的代理路径后缀会导致执行 SomePolicy?

API 调用

GET http://artomatic-test.apigee.net/matchtest/animals

该政策是否执行?否,因为条件需要至少一个由“/**”指定的以下路径元素。

API 调用

GET http://artomatic-test.apigee.net/matchtest/animals/

该政策是否执行?

是,该路径还有另一个路径元素(“/animals/”后面的部分),但它是空的。

API 调用

GET http://artomatic-test.apigee.net/matchtest/animals/cats

该政策是否执行?

是,因为路径中至少有一个元素在“/animals”后面

API 调用

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

该政策是否执行?

是,因为路径在“/animals”后面包含多个元素

混用星号

您可以使用单星号 (*) 和双星号 (**) 的组合,以进一步优化您的路径匹配。

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

API 调用

所有这些 API 调用都会产生匹配项:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild/

GET http://artomatic-test.apigee.net/matchtest/animals/dogs/wild/austrailian



GET http://artomatic-test.apigee.net/matchtest/animals/birds/wild/american/finches

API 资源

RESTful 服务是 API 资源的集合。API 资源是一种 URI 路径片段,用于识别开发者可通过调用 API 访问的某个实体。例如,如果您的服务提供天气报告和天气预报,您的后端服务可能会定义两个 API 资源:

  • http://mygreatweatherforecast.com/reports
  • http://mygreatweatherforecast.com/forecasts

当您创建 API 代理(如构建您的第一个 API 代理中所示)时,您至少创建一个映射到后端服务的别名基础网址。例如:

后端基础网址 新的/等效 API 代理网址
http://mygreatweatherforecast.com http://{your_org}-{environment}.apigee.net/mygreatweatherforecast

此时,您可以使用任一基础网址对后端进行 API 调用。但是,当您使用 API 代理网址时,内容会开始变得有趣。

除了在您使用 API 代理时 Edge 开始收集的 API 分析之外,代理 还可以定义映射到后端资源的条件流。实质上,“如果 /reports 资源发出 GET 调用后,Edge 应该执行一些操作。”

下图显示了最终访问同一后端的两个网址之间的行为差异。一个是未代理资源网址,另一个是 条件流。下面将详细介绍条件流。

API 代理如何映射到特定的后端资源

通过将 API 代理网址映射到后端服务的基础网址(创建代理时),您可以向特定资源添加条件流,例如前面提到的 /reports/forecasts 资源。

假设你希望 Edge “执行某项操作”当有来电 /reports/forecasts 资源。此时,您并未告知 Edge 该做什么,它应该监听对这些资源的调用。您可以使用条件执行此操作。在 Edge API 代理中,您可以为 /reports/forecasts。为了阐明概念,以下 API 代理 XML 展示了这些条件可能的样子。

<Flows>
    <Flow name="reports">
        <Description/>
        <Request/>
        <Response/>
        <Condition>(proxy.pathsuffix MatchesPath "/reports") and (request.verb = "GET")</Condition>
    </Flow>
    <Flow name="forecasts">
        <Description/>
        <Request/>
        <Response/>
        <Condition>(proxy.pathsuffix MatchesPath "/forecasts") and (request.verb = "GET")</Condition>
    </Flow>
</Flows>

这些条件就是,“当 GET 请求传入 /reports/forecasts 后,Edge 将执行您(API 开发者)下达的任务, 将资源应用于这些流

现在,这是一个告知 Edge 在满足条件时要执行的操作的示例。在以下 API 中 发送 GET 请求至 https://yourorg-test.apigee.net/mygreatweatherforecast/reports,Edge 执行 “XML-to-JSON-1”政策。

<Flows>
    <Flow name="reports">
        <Description/>
        <Request/>
        <Response>
            <Step>
                <Name>XML-to-JSON-1</Name>
            </Step>
        </Response>
        <Condition>(proxy.pathsuffix MatchesPath "/reports") and (request.verb = "GET")</Condition>
</Flow>

除了这些可选的条件流之外,每个 API 代理还随附两个默认流:在条件流之前执行的 <PreFlow> 以及在条件流之后执行的 <PostFlow>。在对 API 代理进行任何调用时,这些条件流都有助于执行政策。例如,如果您要在每次调用时验证应用的 API 密钥,则无论访问哪个后端资源,您都可以对 <PreFlow> 添加 Verify API Key 政策。如需详细了解流,请参阅配置流

创建到后端资源的条件流

在 API 代理中,为后端资源定义条件流是可选操作。但是,通过这些条件流,您可以应用精细的管理和监控。

您将能够:

  • 以反映 API 模型语义的方式应用管理
  • 将政策和脚本化行为应用于个别资源路径 (URI)
  • 收集分析服务的精细指标

例如,假设您需要将不同类型的逻辑应用到后端 /developers 和 /apps 资源。

为此,您需要在 API 代理中添加两个条件流:/developers/apps

在 API 代理编辑器“导航器”窗格的“开发”视图中,点击代理端点中的默认值旁边的 + 图标

在“新建条件流”窗口中,输入以下重要配置:

  • 流名称:Developers
  • 条件类型:路径
  • 路径:/developers

如果发送对 URI 末尾含有 /developers 的代理的调用,则会触发条件(并将执行政策)。

现在为 /apps 添加条件流,并假设您要对请求中的 URI 和 POST 谓词触发条件。该配置涉及设置以下内容:

  • 流名称:Apps
  • 条件类型:路径和谓词
  • 路径:/apps
  • 谓词:POST

如果发送对 URI 末尾含有 /apps 和 POST 谓词的代理的调用,则会触发条件(并将执行政策)。

在“导航器”窗格中,您会看到 AppsDevelopers 的新流。

选择其中一个流以在 API 代理编辑器代码视图中查看条件流配置:

<Flow name="Apps">
    <Description>Developer apps registered in Developer Services</Description>
    <Request/>
    <Response/>
    <Condition>(proxy.pathsuffix MatchesPath "/apps") and (request.verb = "POST")</Condition>
</Flow>

如您所见,API 资源只是对入站请求的 URI 路径求值的条件流。(proxy.pathsuffix 变量识别请求的 URI,其跟在 ProxyEndpoint 配置中所配置的 BasePath 后面。)

您定义的每个 API 资源均由 API 代理中的条件流实现。(请参阅配置流。)

将 API 代理部署到测试环境后,以下请求:

http://{org_name}-test.apigee.net/{proxy_path}/apps

将会导致条件的求值结果为 true,且将执行此流以及所有关联的政策。

以下示例条件使用 Java 正则表达式来识别对 /apps 资源(有或没有尾随斜杠:/apps/apps/**)的调用:

<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>

如需详细了解这种类型的条件,请参阅 Apigee 社区中的如何匹配,无论...

为分层 URI 建模

在某些情况下,您会拥有分层 API 资源。例如,Developer Services API 提供了一种方法,用于列出属于某个开发者的所有应用。URI 路径如下:

/developers/{developer_email}/apps

您可能拥有这样的资源:可针对集合中的每个实体生成唯一 ID,集合有时按如下方式注释:

/genus/:id/species

此路径以同等方式应用于以下两个 URI:

/genus/18904/species
/genus/17908/species

如需在 API 资源中表示此结构,您可以使用通配符。例如:

/developers/*/apps
/developers/*example.com/apps
/genus/*/species

将这些分层 URI 作为 API 资源进行适当解析。

在某些情况下,对于深度分层 API,您可能只想解析特定 URI 片段下的所有内容。为此,请在资源定义中使用双星号通配符。例如,如果您定义以下 API 资源:
/developers/**

该 API 资源将解析以下 URI 路径:

/developers/{developer_email}/apps
/developers/{developer_email}/keys
/developers/{developer_email}/apps/{app_id}/keys

在 API 代理定义中,条件流条件如下所示:

<Condition>(proxy.pathsuffix MatchesPath "/developers/**") and (request.verb = "POST")</Condition>

更多示例

附加到 RouteRule 的条件

<RouteRule name="default">
 <!--this routing executes if the header indicates that this is an XML call. If true, the call is routed to the endpoint XMLTargetEndpoint-->
  <Condition>request.header.content-type = "text/xml"</Condition>
  <TargetEndpoint>XmlTargetEndpoint</TargetEndpoint>
</RouteRule>

附加到政策的条件

<Step>
<!--the policy MaintenancePolicy only executes if the response status code is exactly 503-->
  <Condition>response.status.code = 503</Condition>
  <Name>MaintenancePolicy</Name>
</Step>

条件流

<!-- this entire flow is executed only if the request verb is a GET-->
<Flow name="GetRequests">
  <Condition>request.verb="GET"</Condition>
  <Request>
    <Step>
<!-- this policy only executes if request path includes a term like statues-->
<Condition>request.path ~ "/statuses/**"</Condition>
      <Name>StatusesRequestPolicy</Name>
    </Step>
  </Request>
  <Response>
    <Step>
<!-- this condition has multiple expressions. The policy executes if the response code status is exactly 503 or 400-->
<Condition>(response.status.code = 503) or (response.status.code = 400)</Condition>
      <Name>MaintenancePolicy</Name>
    </Step>
  </Response>
</Flow>

条件中的示例运算符

以下是用于创建条件的运算符的一些示例:

  • request.header.content-type = "text/xml"
  • request.header.content-length < 4096 && request.verb = "PUT"
  • response.status.code = 404 || response.status.code = 500
  • request.uri MatchesPath "/*/statuses/**"
  • request.queryparam.q0 NotEquals 10

实例示例:忽略路径末尾的“/”

Edge 开发者通常希望同时处理以下两个路径后缀:“/cat”和 “/cat/”。这是因为某些用户或客户端可能会使用 extra 路径末尾的斜杠,您需要能够在条件语句中 语句。这个具体的用例已在 Apigee 社区中讨论

如果愿意,您可以在不使用 Regex 的情况下实现此目的,如下所示:

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>((proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

这是一个不错的方案。它清楚易懂。

但是,您可以使用正则表达式执行相同的操作,如下面的示例所示。括号用于对语句的正则表达式部分进行分组,但它们不是必需的。

<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>

API 调用

GET http://artomatic-test.apigee.net/matchtest/cat
or

GET http://artomatic-test.apigee.net/matchtest/cat/

该政策是否执行?是。请注意,在正则表达式中,“?”字符表示:匹配零个或一个前面的字符。因此,“/cat”和“/cat/”都是匹配项。

API 调用:

GET http://artomatic-test.apigee.net/matchtest/cat/spotted

该政策是否执行?否。正则表达式匹配零个或一个前面的字符,不允许任何其他字符。

使用 JavaRegex 匹配任意字符串

在本主题的所有示例中,我们演示了如何匹配一个内置流变量:proxy.pathsuffix。不妨了解一下,您可以对任意字符串或流变量进行模式匹配,无论它是否为内置代理变量(如 proxy.pathsuffix)。

例如,如果您的条件可以测试任意字符串,这些字符串可能是后端载荷中返回的字符串,或者是从身份验证服务器查找返回的字符串,则您可以使用匹配的运算符来测试它们。如果使用 JavaRegex,则正则表达式将与整个主题字符串进行比较。如果主题是“abc”,并且正则表达式是“[a-z]”,则没有匹配项,因为“[a-z]”与一个字母字符完全匹配。表达式“[a-z]+”与“[a-z]*”和“[a-z]{3}”一样起作用。

我们来看一个具体的示例。假设身份验证服务器采用以逗号分隔的字符串形式返回角色列表:“editor, author, guest”。

为了测试是否存在 editor 角色,该构造将不起作用,因为“editor”只是整个字符串的一部分。

<Condition>returned_roles ~~ "editor"</Condition>

不过,下面这个构造可以起作用:

<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>

它可以起作用的原因是它通过 .* 前缀和后缀,考虑了字词分开和字符串的任何其他部分。

在该示例中,您还可以使用 Matches 运算符测试“editor”:

<Condition>returned_roles ~~ "*editor*")</Condition>

但是,如果您需要更高的精度,JavaRegex 通常是更好的选择。

将 JavaRegex 表达式中的双引号转义

条件语法要求将 JavaRegex 表达式用双引号引起来;因此,如果您有一个包含英文双引号的正则表达式,则需要采用备用方法来匹配它们。这种方法是 Unicode。例如,假设您传入一个包含双引号的标头,如下所示:
 -H 'content-type:multipart/related; type="application/xop+xml"'
如果您尝试在正则表达式条件中匹配该标头,则会收到“条件无效”错误,因为表达式 包含双引号:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
解决方案是将基于 ASCII 的双引号替换为其对应的 Unicode 双引号 \u0022。例如,以下表达式有效,会产生预期的结果:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"