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

IIS通过ARR转发multipart/form-data上传请求返回502错误排查

问题描述

我们有一个经典ASP.NET Web API对外提供文件上传端点,该接口接收携带文件的multipart/form-data请求,请求格式如下:

POST https://dev.appname.com/api/v2/visitors/{{visitorId}}/attachments/upload
X-API-Key: {{apiKey}}
Content-Type: multipart/form-data; boundary=XXX

--XXX
Content-Disposition: form-data; name="image"; filename="filename.png"
Content-Type: image/png

{{ file bytes }}
--XXX--

我们配置了如下重写规则:

<rule name="Rewrite to dev REST API" enabled="true" stopProcessing="true">
    <match url="api/(v[0-9]+/.*)" />
    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{HTTP_HOST}" matchType="Pattern" pattern="(dev|dev-testing).appname.com" ignoreCase="true" negate="false" />
    </conditions>
    <action type="Rewrite" url="https://restapidev.appname.com/api/{R:1}?tenant={C:1}" appendQueryString="true" />
</rule>

按照上述规则,URL会从https://dev.appname.com/api/v2/visitors/{{visitorId}}/attachments/upload重写为https://restapidev.appname.com/api/v2/visitors/{{visitorId}}/attachments/upload?tenant=dev。
该请求返回502错误,但直接访问https://restapidev.appname.com/api开头的目标URL时,请求可以成功响应。

为了诊断问题,编写了如下代码将请求体写入文件:

private async Task SaveRequestBody() {
  var req = HttpContext.Current.Request;
  using var fileStream = File.OpenWrite($"C:\\temp\\{DateTime.Now:yyyy-MM-dd-HH-mm-ss}-UploadAttachment.txt");
  await req.GetBufferedInputStream().CopyToAsync(fileStream);
}

观测现象

  • 通过dev.appname域名访问时:
    • ❌ 写入的文件为空
  • 直接通过restapidev.appname域名访问时:
    • ✅ 包括上传内容在内的完整请求被写入文件
  • 上传非multipart/form-data格式的文件(Content-Type为image/png,字节直接放在请求体中提交)时:
    • ✅ 包括上传内容在内的完整请求被写入文件

应用日志显示程序在读取请求流时出现“挂起”状态。开启失败请求跟踪后,发现如下记录:

  • 12:36:37.144:触发GENERAL_READ_ENTITY_START事件
  • 12:38:37.504(间隔2分钟后):触发GENERAL_READ_ENTITY_END事件
    • BytesReceived="0",ErrorCode="The I/O operation has been aborted because of either a thread exit or an application request. (0x800703e3)"

注:跟踪日志中还存在REWRITE_DISABLED_KERNEL_CACHE警告,但成功的请求也存在该警告,因此可以排除该告警影响。受限于长度限制,无法贴出完整日志。

综上,Web应用仅在同时满足以下两个条件时会出现读取请求体挂起的问题:

  • 请求为multipart/form-data格式的上传请求
  • 请求经过ARR路由转发

可能的配置错误

以下是对应场景下最常见的配置问题:

  1. ARR请求缓冲配置不匹配
    默认情况下ARR对multipart格式请求的缓冲策略和普通请求存在差异,如果ARR层面的bufferRequestBody配置为false,或是缓冲阈值小于上传文件大小,会导致请求体未完整转发就触发路由逻辑,后端服务读取请求流时无法拿到完整内容触发超时。
    可检查applicationHost.config中的ARR配置,确认对应后端节点的buffer设置为true,同时调整maxAllowedContentLength到大于最大上传文件的大小:
<configuration>
  <system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="104857600" /> <!-- 按实际上传需求调整,示例为100MB -->
      </requestFiltering>
    </security>
    <applicationRequestRouting>
      <webFarms>
        <webFarm name="restapidev.appname.com" enabled="true">
          <server address="restapidev.appname.com" enabled="true" />
          <applicationRequestRouting>
            <protocol buffer="true" />
          </applicationRequestRouting>
        </webFarm>
      </webFarms>
    </applicationRequestRouting>
  </system.webServer>
</configuration>
  1. Content-Type头被意外修改
    部分ARR版本在处理带boundary参数的Content-Type头时,如果存在全局Header重写规则,可能会意外截断或修改boundary值,导致后端服务无法识别multipart请求的边界,持续等待请求体结束触发超时。需检查是否存在全局Header修改规则影响了Content-Type头,必要时在重写规则中显式保留该头。
  2. ASP.NET表单验证提前消费请求体
    经典ASP.NET默认会对multipart/form-data请求提前解析表单内容,将请求流定位到末尾,导致后续ARR转发或业务代码读取时拿到空流。可针对上传接口路径关闭表单自动解析:
<location path="api/visitors/attachments/upload">
  <system.web>
    <httpRuntime maxRequestLength="102400" /> <!-- 对应上方maxAllowedContentLength,单位为KB -->
    <pages validateRequest="false" />
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="false">
      <remove name="FormsAuthentication" />
    </modules>
  </system.webServer>
</location>
  1. ARR超时设置小于上传预期耗时
    如果上传文件较大,ARR默认2分钟的超时时间会在文件上传完成前主动断开连接,和观测到的2分钟后报错的现象完全吻合。可调整ARR超时时间到大于最大上传预期耗时:
<system.applicationHost>
  <webLimits connectionTimeout="00:10:00" /> <!-- 示例调整为10分钟,可按实际需求修改 -->
</system.applicationHost>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 05:36:03