【问题标题】:What happens if more data than the Content-Length is transferred (to the client)?如果传输的数据多于 Content-Length(到客户端),会发生什么情况?
【发布时间】:2021-01-04 07:21:31
【问题描述】:

我正在一个服务器上工作,该服务器接受来自用户的 URL 并下载它(并对它执行其他操作,例如将其上传回来,但这在这里无关紧要)。它应该接受的最大文件大小为 4 GB,这就是用户提供的 URL 必须存在 Content-Length 的原因。

但是,如果恶意服务器提供 2 GB 的 Content-Length 并最终传输 6 GB 会怎样?是否有适当的机制来阻止这种情况?我正在使用 Rust 库 reqwest,但其他 HTTP 客户端的答案也很棒。

【问题讨论】:

  • 我不是这方面的专家,我不确定,但我记得我有同样的问题,答案是客户忽略了其余的数据。由于 HTTP 通过 TCP 传输,因此客户端可能会停止接收数据。顺便说一句,目前,连接可能保持活动状态并且下一个 HTTP 响应随后出现。所以,我不确定在这些情况下到底会发生什么。

标签: http rust content-length reqwest


【解决方案1】:

一个常见的实现将只使用Content-length 并读取指定的尽可能多的数据 - 将剩余数据留在套接字缓冲区(或者可能是一些用户空间缓冲区)中。因此它可能适用于这个特定的请求。

但这实际上可能会在 HTTP 持久连接的情况下造成麻烦。对于Content-length 太短的请求,剩余数据将被解释为同一连接上的另一个 HTTP 请求。对于具有类似问题的响应,剩余数据将被解释为对连接上下一个请求的响应。在最好的情况下,由于数据格式错误,这将被视为错误,请求将被放弃。但在最坏的情况下,它可能会导致安全问题 - 另请参阅 HTTP 请求和响应拆分作为相关攻击。

...这就是 URL 必须存在 Content-Length 的原因

请注意,Content-length 在请求或响应中实际上并不是必需的。消息标头可能没有指示响应的最终大小,因为它可能使用Transfer-Encoding: chunked 或仅以关闭 TCP 连接结束。

【讨论】:

  • 我的服务器希望 Content-Length 标头存在,如果不存在,则会显示错误“无法确定文件大小”。没关系吧?
  • @KreyLazory:这取决于您知道多少或可以控制客户在做什么。使用本地文件上传浏览器当前将发送Content-length 标头。对于其他类型的客户或其他用例 - 谁知道呢。我见过使用传输编码分块而不是内容长度的移动应用程序。
  • @SteffenUllrich 如果我对 OP 的理解正确,这并不是真正的客户端问题,他们的服务器将向其他服务器发送请求,而需要来自其他服务器的响应有content-length。但我想分块编码的问题仍然存在,甚至可能更是如此。
  • @KreyLazory 我实际上并不知道 reqwest,但希望它能够以流的形式为您提供响应,您可以随时停止阅读。那么任何对content-length 的预先检查(如果存在)只会是对发送它的服务器的优化。
  • @MichałPolitowski:你说得对,我确实首先将问题理解为询问响应,然后询问请求 - 但它似乎与响应有关。无论如何,答案现在涵盖了这两种情况,因为影响实际上是相似的。并且对于来自第三方服务器的响应,如果响应是否包含内容长度标头,则可能会更加难以控制。