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

使用Bicep部署XML策略到Azure APIM时遇语法错误求助

Azure APIM策略部署错误修复

错误提示

'=' 是意外令牌。预期令牌为 ';'。第13行,位置58。

原XML策略代码

<policies>
    <inbound>
    <base />
    <choose>
        <when condition="@(!context.Variables.ContainsKey('cachedAccessToken') || DateTime.UtcNow >= (DateTime)context.Variables['tokenExpiry'])">
            <set-backend-service id="apim-generated-policy" backend-id="{0}" />
            <send-request mode="new" response-variable-name="tokenResponse" timeout="20" ignore-error="false">
                <set-url>{1}/token</set-url>
                <set-method>POST</set-method>
                <set-header name="Content-Type" exists-action="override">
                    <value>application/x-www-form-urlencoded</value>
                </set-header>
                <set-body>@("grant_type=password&username={2}&password=thisShouldRefThe-AmxPassword-NamedValue")</set-body>
            </send-request>
            <set-variable name="tokenResponseJson" value="@{{ return JsonConvert.DeserializeObject((string)context.Variables['tokenResponse'].Body.As<string>()); }}" />
            <set-variable name="cachedAccessToken" value="@{{(string)context.Variables['tokenResponseJson']['access_token']}}" />
            <set-variable name="tokenExpiry" value="@{{ return DateTime.UtcNow.AddSeconds((int)context.Variables['tokenResponseJson']['expires_in'] - 60); }}" />
            <cache-store-value key="cachedAccessToken" value="@{{context.Variables['cachedAccessToken']}}" duration="@{{(new TimeSpan(0, (int)context.Variables['tokenResponseJson']['expires_in'], 0))}}" />
            <cache-store-value key="tokenExpiry" value="@{{context.Variables['tokenExpiry']}}" duration="@{{(new TimeSpan(0, (int)context.Variables['tokenResponseJson']['expires_in'], 0))}}" />
        </when>
        <otherwise>
            <cache-lookup-value key="cachedAccessToken" variable-name="cachedAccessToken" />
            <cache-lookup-value key="tokenExpiry" variable-name="tokenExpiry" />
        </otherwise>
    </choose>
    <set-header name="Authorization" exists-action="override">
        <value>@{{$"Bearer {context.Variables['cachedAccessToken']}"}}</value>
    </set-header>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

流水线用Bicep代码

resource apim 'Microsoft.ApiManagement/service@2022-04-01-preview' existing = {
    name: apimName

    resource apiVersionSet 'api-version-sets@2018-06-01-preview' = if (enableApiVersioning) {
        name: apiName
        properties: {
            displayName: displayName
            versioningScheme: versionScheme
            versionHeaderName: 'X-Api-Version'
            versionQueryName: 'api-version'
        }
    }

    resource api 'apis' = {
        name: enableApiVersioning ? apiNameVersioned : apiName
        properties: {
            displayName: displayName
            path: '${pathPrefix}${apiName}'
            format: definitionFormat
            protocols: [
                'https'
            ]
            subscriptionRequired: true
            value: definition
            apiVersion: enableApiVersioning ? version : null
            apiVersionSetId: enableApiVersioning ? apiVersionSet.id : null
            subscriptionKeyParameterNames: {
                header: 'Ocp-Apim-Subscription-Key'
                query: 'subscription-key'
            }
        }

        resource apiPolicy 'policies' = if (!empty(policy)) {
            name: 'policy'
            properties: {
                value: policy
            }
        }
    }
}

问题根源与修复

错误是因为XML策略里的表达式语法不符合APIM规范:

  • APIM策略表达式必须用@(...)包裹,你用了@{{ ... }},这种写法会让解析器误判令牌,触发报错。
  • 同时原策略里引用命名值的方式不对,无法正确读取APIM中的密码命名值。

修复后的XML策略:

<policies>
    <inbound>
    <base />
    <choose>
        <when condition="@(!context.Variables.ContainsKey("cachedAccessToken") || DateTime.UtcNow >= (DateTime)context.Variables["tokenExpiry"])">
            <set-backend-service id="apim-generated-policy" backend-id="{0}" />
            <send-request mode="new" response-variable-name="tokenResponse" timeout="20" ignore-error="false">
                <set-url>{1}/token</set-url>
                <set-method>POST</set-method>
                <set-header name="Content-Type" exists-action="override">
                    <value>application/x-www-form-urlencoded</value>
                </set-header>
                <set-body>@($"grant_type=password&username={2}&password={context.Deployment.NamedValues["AmxPassword"].Value}")</set-body>
            </send-request>
            <set-variable name="tokenResponseJson" value="@(JsonConvert.DeserializeObject((string)context.Variables["tokenResponse"].Body.As<string>()))" />
            <set-variable name="cachedAccessToken" value="@((string)context.Variables["tokenResponseJson"]["access_token"])" />
            <set-variable name="tokenExpiry" value="@(DateTime.UtcNow.AddSeconds((int)context.Variables["tokenResponseJson"]["expires_in"] - 60))" />
            <cache-store-value key="cachedAccessToken" value="@(context.Variables["cachedAccessToken"])" duration="@(new TimeSpan(0, (int)context.Variables["tokenResponseJson"]["expires_in"], 0))" />
            <cache-store-value key="tokenExpiry" value="@(context.Variables["tokenExpiry"])" duration="@(new TimeSpan(0, (int)context.Variables["tokenResponseJson"]["expires_in"], 0))" />
        </when>
        <otherwise>
            <cache-lookup-value key="cachedAccessToken" variable-name="cachedAccessToken" />
            <cache-lookup-value key="tokenExpiry" variable-name="tokenExpiry" />
        </otherwise>
    </choose>
    <set-header name="Authorization" exists-action="override">
        <value>@($"Bearer {context.Variables["cachedAccessToken"]}")</value>
    </set-header>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

修复要点:

  • 把所有@{{ ... }}替换成@(...),符合APIM表达式语法要求。
  • 修正密码命名值的引用方式为context.Deployment.NamedValues["AmxPassword"].Value,确保能正确读取APIM中配置的命名值。
  • 移除不必要的return语句,简化表达式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:15:03