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"}]
问题分析与修复方案
问题根源
- XML引号转义错误:原策略中
condition属性内嵌套的双引号未正确转义,导致XML解析器认为属性提前结束,触发语法错误。 - Terraform变量渲染失效:
var.api.rate_limit未被正确渲染,输出中显示为空值,说明变量传递或渲染逻辑存在问题。 - 冗余变量定义:额外定义的
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 }
关键优化点
- XML转义处理:使用Terraform Heredoc语法编写XML内容,避免手动转义双引号的麻烦。
- 条件逻辑简化:直接在
condition中用string.IsNullOrEmpty判断速率限制是否存在,同时直接校验JWT和Subscription ID,去掉冗余变量。 - 变量渲染保障:确保
var.api.rate_limit有值时才会触发限流逻辑,空值时条件不成立,避免空值注入导致的策略错误。
内容的提问来源于stack exchange,提问作者Panda
相关产品推荐
相关产品推荐

