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

Azure API Management中return-response调用POST API返回400错误排查

解决Azure API Management出站策略POST调用400错误问题

问题场景

我在Azure API Management的出站策略中设置逻辑:检查GET API的响应体,若entityStatus字段值为0,则返回提示消息;若值为1,则调用外部POST API并返回其响应。

原策略代码:

<set-variable name="id" value="" />
<set-variable name="newRequest" value="@(context.Request.Body?.As<JObject> 
       (preserveContent: true))" />
<choose>
 <when condition="@(context.Response.StatusCode == 200 && 
 (int)context.Response.Body?.As<JObject>(true)["entityStatus"] == 1)">
<send-request mode="new" timeout="20" response-variable-name="id" ignore-error="false">
    <set-url>@($"https://api.dev/external/workrequest/wr")</set-url>
    <set-method>POST</set-method>
    <set-header name="Content-Type" exists-action="override">
        <value>application/json</value>
    </set-header>
    <set-header name="Authorization" exists-action="override">
    <value>@(context.Request.Headers.GetValueOrDefault("Authorization","scheme param"))</value>
    </set-header>
    <set-body>@{ var document = (JObject)context.Variables["newRequest"];
                  return document?.ToString();
                }</set-body>
</send-request>
<return-response response-variable-name="id">
    <set-status code="200" reason="OK" />
    <set-header name="Content-Type" exists-action="override">
        <value>application/json</value>
    </set-header>
    <set-body>@((((IResponse)context.Variables["id"]).Body.As<JObject>()).ToString())</set-body>
</return-response>
</when>
<when condition="@(context.Response.StatusCode == 200 && (int)context.Response.Body?.As<JObject>(true)["entityStatus"] == 0)">
    <return-response>
        <set-status code="500" reason="VOID" />
        <set-header name="Content-Type" exists-action="override">
            <value>application/json</value></set-header>
        <set-body>The record is void</set-body>
     </return-response>
</when>
<otherwise />
</choose>

错误现象

当entityStatus为0时返回正常,但为1时触发400错误:

{
"type": "https://httpstatuses.io/400",
"title": "Bad Request",
"status": 400,
"traceId": "00-317b53ba7a76f19b6153ca6ab14c5190-e9c27cf9162e2414-00"
}

解决方案

1. 修正请求体来源(核心问题)

原策略中newRequest变量取的是原GET请求的Body,但GET请求通常没有Body,导致传递给外部POST API的内容为空,触发400错误。需要改为从GET API的响应体中提取数据作为POST请求体:

<!-- 替换原newRequest变量,从响应体获取数据 -->
<set-variable name="responseBody" value="@(context.Response.Body?.As<JObject>(preserveContent: true))" />

<!-- 在send-request的set-body中使用响应体数据 -->
<set-body>@{ 
    var document = (JObject)context.Variables["responseBody"];
    // 若外部API需要特定字段,可在此筛选,如return document["targetField"]?.ToString();
    return document?.ToString();
  }</set-body>

2. 添加日志排查请求内容

在send-request前添加日志,确认传递给外部API的内容是否符合要求:

<trace source="POST-Request-Debug" severity="information">@($"POST Body: {((JObject)context.Variables["responseBody"]).ToString()}")</trace>

3. 优化返回响应逻辑

添加空值判断,避免强制转换异常,并保留外部API的原始状态码:

<return-response response-variable-name="externalResponse">
    <set-status code="@(((IResponse)context.Variables["externalResponse"]).StatusCode)" reason="@(((IResponse)context.Variables["externalResponse"]).ReasonPhrase)" />
    <set-header name="Content-Type" exists-action="override">
        <value>application/json</value>
    </set-header>
    <set-body>@{
        var externalResponse = (IResponse)context.Variables["externalResponse"];
        return externalResponse.Body?.As<JObject>(preserveContent: true)?.ToString() ?? "{}";
      }</set-body>
</return-response>

完整修复后策略示例

<set-variable name="responseBody" value="@(context.Response.Body?.As<JObject>(preserveContent: true))" />
<choose>
 <when condition="@(context.Response.StatusCode == 200 && (int)context.Response.Body?.As<JObject>(true)["entityStatus"] == 1)">
    <trace source="EntityStatus-1" severity="information">@("触发外部POST API调用")</trace>
    <send-request mode="new" timeout="20" response-variable-name="externalResponse" ignore-error="false">
        <set-url>@($"https://api.dev/external/workrequest/wr")</set-url>
        <set-method>POST</set-method>
        <set-header name="Content-Type" exists-action="override">
            <value>application/json</value>
        </set-header>
        <set-header name="Authorization" exists-action="override">
        <value>@(context.Request.Headers.GetValueOrDefault("Authorization","scheme param"))</value>
        </set-header>
        <set-body>@{ 
            var document = (JObject)context.Variables["responseBody"];
            return document?.ToString();
          }</set-body>
    </send-request>
    <return-response response-variable-name="externalResponse">
        <set-status code="@(((IResponse)context.Variables["externalResponse"]).StatusCode)" reason="@(((IResponse)context.Variables["externalResponse"]).ReasonPhrase)" />
        <set-header name="Content-Type" exists-action="override">
            <value>application/json</value>
        </set-header>
        <set-body>@{
            var externalResponse = (IResponse)context.Variables["externalResponse"];
            return externalResponse.Body?.As<JObject>(preserveContent: true)?.ToString() ?? "{}";
          }</set-body>
    </return-response>
</when>
<when condition="@(context.Response.StatusCode == 200 && (int)context.Response.Body?.As<JObject>(true)["entityStatus"] == 0)">
    <return-response>
        <set-status code="500" reason="VOID" />
        <set-header name="Content-Type" exists-action="override">
            <value>application/json</value></set-header>
        <set-body>The record is void</set-body>
     </return-response>
</when>
<otherwise />
</choose>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:05:32