探索 API 管理策略

已完成

在 Azure API 管理中,策略允许发布者通过配置更改 API 的行为。 策略是一组语句,在请求或响应 API 时按顺序执行。

策略在网关内部应用,该网关位于 API 使用者和托管 API 之间。 该网关接收所有请求,并通常将其原封不动地转发到基础 API。 但是策略可以将更改应用于入站的请求和出站响应。 在任何 API 管理策略中,策略表达式可以用作属性值或文本值,除非该策略另外指定。

了解策略配置

策略定义是一个简单的 XML 文档,用于描述一个入站和出站语句序列。 可以直接在定义窗口中编辑 XML。

配置划分为 inboundbackendoutboundon-error。 指定的策略语句系列将按请求和响应顺序执行。

<policies>
  <inbound>
    <!-- statements to be applied to the request go here -->
  </inbound>
  <backend>
    <!-- statements to be applied before the request is forwarded to 
         the backend service go here -->
  </backend>
  <outbound>
    <!-- statements to be applied to the response go here -->
  </outbound>
  <on-error>
    <!-- statements to be applied if there is an error condition go here -->
  </on-error>
</policies>

如果在处理请求的过程中出错,则会忽略 inboundbackendoutbound 部分的其余步骤,跳到 on-error 部分执行相关语句。 将策略语句置于 on-error 部分以后,即可使用 context.LastError 属性查看错误、使用 set-body 策略检查和自定义错误响应,以及配置发生错误时的应对措施。

策略表达式

在任何 API 管理策略中,策略表达式都可以用作属性值或文本值,除非该策略另外指定。 策略表达式为:

  • 括在 @(expression) 中的单个 C# 语句,或
  • 括在 @{expression} 中的多语句 C# 代码块,它返回一个值

每个表达式可以访问隐式提供的 context 变量以及允许的 .NET Framework 类型子集。

策略表达式提供一种复杂的方式用于控制流量和修改 API 行为,而无需编写专用的代码或修改后端服务。

以下示例使用策略表达式和 set-header 策略将用户数据添加到传入的请求。 添加的标头包含与请求中的订阅密钥关联的用户 ID,以及处理请求的网关所在的区域。

<policies>
    <inbound>
        <base />
        <set-header name="x-request-context-data" exists-action="override">
            <value>@(context.User.Id)</value>
            <value>@(context.Deployment.Region)</value>
      </set-header>
    </inbound>
</policies>

应用在不同范围指定的策略

如果你在全局级别有一个策略并且为 API 配置一个策略,则只要使用该特定 API,这两个策略都将被应用。 API 管理允许通过基础元素实现组合策略声明的确定性排序。

<policies>
    <inbound>
        <cross-domain />
        <base />
        <find-and-replace from="xyz" to="abc" />
    </inbound>
</policies>

在上述策略定义示例中,首先执行 cross-domain 语句。 在应用更宽泛范围的所有策略之后执行 find-and-replace 策略。

筛选响应内容

以下示例中定义的策略演示了如何基于与请求关联的产品从响应有效负载中筛选数据元素。

该代码片段假定响应内容的格式设置为 JSON,并且包含名为“minutely”、“hourly”、“daily”、“flags”的根级别属性。

<policies>
  <inbound>
    <base />
  </inbound>
  <backend>
    <base />
  </backend>
  <outbound>
    <base />
    <choose>
      <when condition="@(context.Response.StatusCode == 200 && context.Product.Name.Equals("Starter"))">
        <!-- NOTE that we are not using preserveContent=true when deserializing response body stream into a JSON object since we don't intend to access it again. See details on /azure/api-management/api-management-transformation-policies#SetBody -->
        <set-body>
          @{
            var response = context.Response.Body.As<JObject>();
            foreach (var key in new [] {"minutely", "hourly", "daily", "flags"}) {
            response.Property (key).Remove ();
           }
          return response.ToString();
          }
    </set-body>
      </when>
    </choose>    
  </outbound>
  <on-error>
    <base />
  </on-error>
</policies>