You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure API Management策略:无法添加空字符串检查条件

问题描述

我正在为已接入的多个API添加专属策略,计划根据API所有者在配置文件中提供的速率限制设置限流。部分API提供速率限制,部分未提供;同时API采用JWT或subscription_id两种认证方式。需求是:当API所有者提供了速率限制,且API通过JWT/subscription_id认证时,应用指定的限流规则,否则不执行任何操作。

尝试的代码

API策略XML

<policies>
     <inbound>
       <set-variable name="isjwt" value="@(context.Request.Headers.GetValueOrDefault('Authorization', '').AsJwt()?.Subject)" />
       <set-variable name="isSubId" value="@(context.Subscription.Id)" />
           
       <choose>
          <when condition="(${var.api.rate_limit} != "" and (context.Variables["isjwt"] != null or context.Variables["isSubId"] != null))">
              <rate-limit-by-key calls=${var.api.rate_limit} renewal-period="60" counter-key="@(context.Variables["isjwt"] ?? context.Variables["isSubId"])" />
           </when>
        </choose>
       </inbound>
       <backend>
       <base />
       </backend>
       <outbound>
       <base />
       </outbound>
       <on-error>
       <base />
       </on-error>
      </policies>

Terraform变量定义

variable "api" {
    type = object({
    name = string
    rate_limit = string
    })
}

Terraform计划输出

+         <set-variable name="isAuthenticated" value="@(context.Request.Headers.GetValueOrDefault('Authorization', '').AsJwt()?.Subject)" />
  +         <set-variable name="hasSubscriptionId" value="@(context.Subscription.Id)" />
  + 
  +         <choose>
  +          <when condition="( != ""  and (context.Variables["isjwt"] != null or context.Variables["isSubId"] != null))">
  +               <rate-limit-by-key calls="" renewal-period="60" counter-key="@(context.Variables["isjwt"] ?? context.Variables["isSubId"])" />
  +           </when>
  +         </choose>

错误信息

错误:创建/更新API策略:(策略名称"xml" / API名称"APINAME" / 服务名称"SERVICENAME" / 资源组"RGNAME"):apimanagement.APIPolicyClient#CreateOrUpdate:响应请求失败:StatusCode=400 -- 原始错误:autorest/azure:服务返回错误。状态=400 代码="ValidationError" 消息="一个或多个字段包含不正确的值:" 详细信息=[{"code":"ValidationError","message":"名称不能以'"'字符开头,十六进制值0x22。第36行,第52位。","target":"representation"}]


问题分析与修复方案

问题根源

  1. XML引号转义错误:原策略中condition属性内嵌套的双引号未正确转义,导致XML解析器认为属性提前结束,触发语法错误。
  2. Terraform变量渲染失效:var.api.rate_limit未被正确渲染,输出中显示为空值,说明变量传递或渲染逻辑存在问题。
  3. 冗余变量定义:额外定义的isjwt和isSubId变量无必要,可直接在表达式中判断。

修正后的代码

API策略XML(结合Terraform Heredoc避免转义问题)

resource "azurerm_api_management_api_policy" "api_policy" {
  api_name            = azurerm_api_management_api.target_api.name
  api_management_name = azurerm_api_management.example.name
  resource_group_name = azurerm_resource_group.example.name

  xml_content = <<XML
<policies>
  <inbound>
    <choose>
      <when condition="@(!string.IsNullOrEmpty("${var.api.rate_limit}") && (context.Request.Headers.GetValueOrDefault('Authorization', '').AsJwt()?.Subject != null || context.Subscription.Id != null))">
        <rate-limit-by-key calls="${var.api.rate_limit}" renewal-period="60" counter-key="@(context.Request.Headers.GetValueOrDefault('Authorization', '').AsJwt()?.Subject ?? context.Subscription.Id)" />
      </when>
    </choose>
    <base />
  </inbound>
  <backend>
    <base />
  </backend>
  <outbound>
    <base />
  </outbound>
  <on-error>
    <base />
  </on-error>
</policies>
XML
}

关键优化点

  1. XML转义处理:使用Terraform Heredoc语法编写XML内容,避免手动转义双引号的麻烦。
  2. 条件逻辑简化:直接在condition中用string.IsNullOrEmpty判断速率限制是否存在,同时直接校验JWT和Subscription ID,去掉冗余变量。
  3. 变量渲染保障:确保var.api.rate_limit有值时才会触发限流逻辑,空值时条件不成立,避免空值注入导致的策略错误。

内容的提问来源于stack exchange,提问作者Panda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:00:35