【问题标题】:Why "Content-Length: 0" in POST requests?为什么在 POST 请求中出现“Content-Length: 0”?
【发布时间】:2010-09-24 14:30:41
【问题描述】:

客户有时会在提交表单时使用Content-Length: 0 发送 POST 请求(10 到 40 多个字段)。

我们在不同的浏览器和不同的位置对其进行了测试,但无法重现错误。客户正在使用 Internet Explorer 7 和代理。

我们要求他们让系统管理员从他们的角度了解问题。在没有代理的情况下运行一些测试等。

与此同时(半年后仍然没有答案)我很好奇其他人是否知道Content-Length: 0请求的类似问题。可能来自某些 Windows 网络内部,为大公司提供了特殊代理。

Internet Explorer 7 是否存在已知问题?使用代理系统? Windows 网络本身?

Google 仅在 NTLM(和此类)身份验证的上下文中显示了某些内容,但我们并未在 Web 应用程序中使用它。可能是代理在使用 Windows 登录的客户网络中运行的方式? (我不是 Windows 专家。只是猜测。)

我没有关于基础架构的更多信息。

更新: 2010 年 12 月,可以将此通知一位管理员,包括。来自这里的答案的链接。联系也是因为代理引起的另一个问题。从那以后没有任何反馈。并且错误消息仍然存在。我笑是为了不让我哭。

更新 2: 这个问题自 2008 年中期以来就存在。每隔几个月,客户就会感到恼火,并希望尽快修复它。我们再次向他们发送所有旧电子邮件,并要求他们联系他们的管理员来修复它或运行一些进一步的测试。 2010 年 12 月,我们能够向 1 位管理员发送一些信息。没有反馈。问题没有解决,我们不知道他们是否尝试过。并且在 2011 年 5 月,客户再次写信并希望解决此问题。自 2008 年以来拥有所有信息的同一个人。

感谢您的所有回答。正如我从这里的一些 cmets 中看到的那样,你帮助了很多人。太糟糕了,现实世界对我来说是这样的怪诞。

更新 3: 2012 年 5 月,我想知道为什么我们没有收到另一个解决此问题的要求(请参阅更新 2)。调查了错误协议,它每次发生时只报告这个单一的错误(大约每天 15 次)。它于 2012 年 1 月结束。没有人说什么。他们一定对他们的网络做了什么。现在一切正常。从 2008 年夏天到 2012 年 1 月。可惜我不能告诉你他们做了什么。

更新 4: 2015 年 9 月。该网站必须收集一些数据并将其传送到客户的主网站。有一个带有帐户的 API。每当出现问题时,他们都会联系我们,即使问题显然在另一边。几个星期以来,我们无法向他们发送数据。该帐户不再可用。他们重新启动了,我再也找不到使用我们网站数据的页面了。错误报告没有得到答复,也没有人抱怨。我猜他们刚刚结束了这个项目。

更新 5: 2017 年 3 月。该 API 在 2015 年夏天停止工作。客户似乎继续为该网站付费,并且在 2017 年 2 月仍在访问它。我猜他们使用它作为一个档案。他们不再创建或更新任何数据,因此这个错误可能不会在 2012 年 1 月的神秘修复之后重新出现。但这将是其他人的问题。我要走了。

【问题讨论】:

  • 我怀疑是代理。我的猜测是浏览器实际上并没有发送 Content-Length 标头,并且代理用它“看到”的值填充它:no value == 0。
  • 这个header的存在给你带来了什么问题?
  • @Joel:不是标题,而是缺少的内容。空荡荡的身体。应用程序需要一些数据并引发错误。
  • @stesch:太棒了!我刚刚重新打开了 5 年前客户的错误报告。我阅读了我的票证更新,这些更新通过谷歌引导我查看您的报告 :-) 您报告的设置与我的一位客户匹配。客户运行相同的设置。 IE7 后面有一个代理。现在他们正在使用IE8,但错误仍然时有发生。该错误似乎与特定形式有关。我怀疑代理是罪魁祸首。您还记得您的客户使用了哪个代理吗?我看到“HTTP_VIA '1.1 LANPROXY'”。不知道实际的代理产品叫什么。我可以询问是否有人感兴趣。
  • 这个注册表项解决了这个问题:stackoverflow.com/a/41004109/129346

标签: windows internet-explorer http web-applications proxy


【解决方案1】:

您确定这些请求来自“客户”吗?

我以前遇到过机器人问题;他们有时会根据他们在抓取过程中发现的 FORM 标记中的操作 URI 发送空白 POST 请求来探测站点以查找“联系我们”表单。

【讨论】:

  • 每个 0-POST 错误都会触发一封带有用户名和请求标头的电子邮件。我确定。
【解决方案2】:

在 https 连接达到 keepalive 超时并重新连接到服务器后,Google 还会将此显示为 IE(无论如何都是某些版本)错误。解决方案似乎是配置服务器在https下不使用IE的keepalive。

【讨论】:

    【解决方案3】:

    HTTP 中 ContentLength 标头的存在和可能值在 HTTP(我假设 1/1)RFC 中进行了描述:

    http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13

    在 HTTP 中,只要可以在传输之前确定消息的长度,就应该发送它

    另见:

    如果收到一条消息 Transfer-Encoding 头域和一个 Content-Length 头域, 后者必须被忽略。 http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

    也许您的消息带有 Transfer-Encoding 标头?

    稍后编辑:另请注意 RFC 中使用的“应该”非常重要,并不等同于“必须”:

    3.应该这个词,或形容词“推荐”,意味着有 在特定情况下可能存在忽略一个 特定项目,但必须了解全部含义并 在选择不同的课程之前仔细权衡。 参考:http://www.ietf.org/rfc/rfc2119.txt

    【讨论】:

    • 无传输编码。 :-( 听起来很合理,我在脑海中构建了一些进一步的解释……但标题中没有传输编码。
    • 这解释了为什么它存在,即使服务器应该忽略它。
    【解决方案4】:

    如果表单字段从经过身份验证的站点 (NTLM) 发布到未经过身份验证的站点(匿名),Internet Explorer 不会发送它们。

    这是针对挑战响应情况(NTLM 或 Kerberos 安全网站)的功能,其中 IE 可以预期第一个 POST 请求会立即导致 HTTP 401 Authentication Required 响应(其中包括挑战),并且实际上只接受第二个 POST 请求(包括对挑战的响应)。在这些情况下,出于性能原因,IE 不会将可能较大的请求正文与第一个请求一起上传。感谢 EricLaw 在 cmets 中发布这些信息。

    每次从 NTLM 身份验证(即 Intranet)页面到非身份验证(即 Internet)页面的 HTTP POST 时,或者如果非身份验证页面是框架集的一部分,框架集页面已通过身份验证。

    解决方法是使用 GET 请求作为表单方法,或者确保未经过身份验证的页面在没有部分经过身份验证的框架集的情况下在新的选项卡/窗口(收藏夹/链接目标)中打开。一旦整个窗口的认证模型一致,IE就会重新开始发送表单内容。


    【讨论】:

    • 框架集?这可能是。客户不是很容易接近,所以很难问。 (他们甚至不关心问自己的 IT,但关心不时抱怨。)但我可以在代码中包含一个帧转义,看看我是否得到更多错误。
    • 可能是转码不够用。 IE 非常坚持记住该窗口曾经(至少部分地)通过 NTLM 身份验证。不过,我期待听到它的进展情况。
    • 这是迄今为止最有希望的答案。我要等到星期五,在赏金结束之前。最后一个错误是在我安装 frame escape 之前的 6 分钟。
    • @Tomalak - 谢谢,我有这个确切的问题,它是可复制的,所以我可以修复它......
    • 这个答案中的“安全”声明实际上是不准确的。有问题的行为在这里解释:blogs.msdn.com/b/ieinternals/archive/2010/11/22/…
    【解决方案5】:

    这是 Internet explorer 6 的一个已知问题,但不是我所知道的 7。您可以为 IE6 KB831167 修复安装此修复。

    您可以read more about it here。

    问你一些问题:

    • 您知道哪种类型的代理吗?
    • 您知道请求中是否发送了实际的正文吗?
    • 是否每次都始终如一地发生?还是只是有时?
    • 请求中是否发送了任何二进制数据?也许数据以 \0 开头,并且代理有二进制数据的错误。

    【讨论】:

    • 问题是,我无法安装任何东西。难缠的顾客。他们正在使用 IE7。他们甚至不联系自己的 IT 部门在没有代理的情况下进行尝试。
    • 类型未知。未发送正文(发生此问题时)。不规律的。没有二进制文件。
    【解决方案6】:

    问题很可能是中间的代理服务器实现了 HTTP 1.0。

    在 HTTP 1.0 中,您必须使用 Content-Length 标头字段:(See section 10.4 here)

    需要有效的内容长度 所有 HTTP/1.0 POST 请求。一个 HTTP/1.0 服务器应该以 400(错误请求)消息,如果它不能 确定请求的长度 消息的内容。

    进入代理的请求是 HTTP 1.1,因此不需要使用 Content-Length 标头字段。通常使用 Content-Length 标头,但并非总是如此。请参阅HTTP 1.1 RFC S. 14.13 的以下摘录。

    应用程序应该使用这个字段来 表示的传输长度 消息体,除非这是 被section 4.4 中的规则禁止。 任何内容长度大于或 等于零是一个有效值。

    4.4 部分描述了如何确定 消息体的长度,如果 a 没有给出内容长度。

    所以代理服务器看不到 Content-Length 标头,它假设在 HTTP 1.0 中如果有正文是绝对需要的。因此它假定为 0,以便请求最终到达服务器。请记住,代理不知道 HTTP 1.1 规范的规则,因此它不知道如何处理没有 Content-Length 标头的情况。

    您是否 100% 确定您的请求指定了 Content-Length 标头?如果它使用第 4.4 节中定义的另一种方式,因为它认为服务器是 1.1(因为它不知道介于两者之间的 1.0 代理),那么您将遇到所描述的问题。

    也许您可以改用 HTTP GET 来绕过该问题。

    【讨论】:

      【解决方案7】:

      我们的系统上有一位客户遇到了完全相同的问题。我们已将其指向代理/防火墙。微软的 IAS。它正在剥离 POST 正文并发送 content-length: 0。然而,我们可以做的不多,并且想要使用 GET 请求,因为这会在 URL 字符串上暴露用户名/密码等。我们的系统上有近 7,000 名用户,只有一个有问题……也只有一个使用 Microsoft IAS,所以必须是这样。

      【讨论】:

      • 3 年后我们使用相同的代理产品遇到了完全相同的问题。
      【解决方案8】:

      微软对KB821814的修复可以将Content-Length设置为0:

      本文介绍的修补程序将 Wininet.dll 中的代码更改为:

      • 检测 POST 请求的 RESET 条件。
      • 保存要发布的数据。
      • 在内容长度设置为 0 的情况下重试 POST 请求。这样可以防止发生重置并允许完成身份验证过程。
      • 重试原始 POST 请求。

      【讨论】:

        【解决方案9】:

        这很容易通过 MS-IE 和服务器端的 NTLM 身份验证过滤器重现。我对 XP-SP2 上的 JCIFS (1.2.)、struts 1. 和 MS-IE 6/7 有同样的问题。终于修好了。有几种解决方法可以弥补。

        1. 将表单方法从 POST(struts 默认设置)更改为 GET。 对于大多数具有小尺寸表单的页面,它运行良好。不幸的是,我可能有超过 50 条记录要在 HTTP 流中发送回服务器端。 IE 的 GET URL 限制为 2038 字节(不是参数长度,而是整个 URL 长度)。所以这是一个快速的解决方法,但不适用于我。

        2. 在执行 POST 操作之前发送一个 GET。 这是在 MS-KB 中推荐的。我的项目有许多遗留程序,我不会在正确的时间冒险。我从未尝试过这个,因为根据我对 MS-KB 的理解,当过滤层接收到 GET 时,它仍然需要一些额外的身份验证处理,并且我不想改变其他浏览器的行为,例如火狐,歌剧。

        3. 检测是否以零内容长度发送 POST(您可以使用框架从标头属性哈希结构中获取它)。 如果是这样,请通过从 DC 或缓存中获取质询代码来触发 NTLM 身份验证周期,并期待 NTLM 响应。 当收到 NTLM type2 msg 并且会话仍然有效时,您实际上不需要对用户进行身份验证,只需将其转发到预期的操作(如果 POST content-length 不为零)。顺便说一句,这会增加网络流量。因此,请在应用更改之前检查您的缓存寿命设置和 SMB 会话 soTimeOut 配置。 或者,更简单,您可以只向 MS-IE 发送 401 未授权状态,然后浏览器将发送回 POST 请求和数据作为回复。

        4. MS-KB 提供了一个带有 KB-923155 的热修复(由于信誉数低,我无法发布多个链接 :{ ),但它似乎不起作用。有人会在这里发布一个可行的热修复吗?谢谢 :) 这是一个参考链接,http://www.websina.com/bugzero/kb/browser-ie.html

        【讨论】:

          【解决方案10】:

          如果用户正在通过使用 NTLM 身份验证的 ISA 代理,那么听起来像这个问题,它提供了解决方案(ISA 代理的补丁)

          http://support.microsoft.com/kb/942638
          可能会将没有 POST 正文的 POST 请求发送到在 ISA Server 2006 中发布的 Web 服务器

          【讨论】:

            【解决方案11】:

            我们有一位客户在匿名和 NTLM 模式下使用同一网站(在不同的端口上)。我们发现,在我们的案例中,401 与用于 http 优化的 Riverbed Steelhead 应用程序有关。将我们指向该方向的第一个信号是 X-RBT-Optimized-By 标头。问题在于免费的 401 功能:

            此功能可用于每个请求和每个连接 身份验证,但与每个请求一起使用时最有效 验证。使用按请求身份验证,每个请求都必须是 在服务器提供服务之前针对服务器进行身份验证 反对客户。但是,大多数浏览器不会缓存服务器的 需要身份验证的响应,因此它会浪费一个 每个 GET 请求的往返。使用 Gratuitous 401,客户端 Steelhead 设备将缓存服务器响应以及何时客户端 发送没有任何身份验证标头的 GET 请求,它将 本地响应“401 Unauthorized”消息并因此保存 往返。请注意,HTTP 模块不参与 实际身份验证本身。 HTTP 模块的作用是通知 服务器需要身份验证而不需要的客户端 它浪费了一个往返。

            【讨论】:

              【解决方案12】:

              curl 在配置为使用 HTTP 代理时发送带有 Content-Length: 0 的 PUT/POST 请求。在第一次未经授权的PUT/POST 请求代理的情况下,克服所需的缓冲是一个技巧。在GET/HEAD 请求curl 的情况下,只需重复查询。 PUT/POST 的方案如下:

              1. 发送第一个 PUT/POST 请求,并将 Content-Length 设置为 0。

              2. 得到答案。 HTTP 状态码 407 意味着我们必须使用代理 授权。为发送请求准备代理身份验证的标头。

              3. 再次发送请求,并使用已填充的标头进行代理身份验证,并将真实数据发送到 POST/PUT。

              【讨论】:

                【解决方案13】:

                我还有一个问题,来自客户的 IE 11 浏览器的请求包含 Content-Length: 0 并且不包含预期的 POST 内容。当客户使用 Firefox 或 Chrome 时,请求中包含预期的内容。

                我发现原因是客户使用的是 HTTP URL 而不是 HTTPS URL(例如 http://...,而不是 https://...),而我们的应用程序使用 HSTS。似乎 IE 11 中可能存在一个错误,即当请求由于 HSTS 升级到 HTTPS 时,请求内容会丢失。

                让客户将 URL 更正为 https://... 导致内容包含在 POST 请求中并解决了问题。

                现阶段我还没有进一步调查这是否真的是 IE 11 中的错误。

                【讨论】:

                • 谢谢!!!我只是花了一整天的时间追着我的尾巴看 NTLM 优化红鲱鱼。事实证明,这一直是 IE11 中的一个错误。事实证明,Windows 10 上的 IE11 似乎忽略了 HSTS 注册表设置,所以即使你告诉它不要这样做(与 Windows 7 不同),它仍然会这样做,所以在升级到 Windows 10 之前我们从未注意到这一点。
                猜你喜欢
                • 2010-11-17
                • 2023-03-07
                • 1970-01-01
                • 1970-01-01
                • 2010-09-07
                • 1970-01-01
                • 2020-09-21
                • 1970-01-01
                • 2012-01-05
                相关资源
                最近更新 更多