服务器在接收完整个请求之前发送HTTP响应是否可行?

59

考虑一个大型的HTTP请求:

POST /upload HTTP/1.1
Content-Type: multipart/form-data
Content-Length: 1048576

...

客户端现在开始上传1MB的数据,这可能需要一些时间。然而,服务器确定需要HTTP授权,因此它决定用HTTP 401 Unauthorized作为响应。

在服务器能够响应之前,它是否必须等到完整的请求(即头部+ CRLF CRLF + Content-Length字节)都接收到了?

从实际情况来看,这种行为会导致浏览器崩溃吗?浏览器是否继续上传文件,还是如果它们接收到“不完整”的响应就停止传输?

更重要的是,在这种情况下,它们是否能够成功验证并重新开始上传(使用凭据),或者像这样中断上传是不可靠的?


那么你找到答案了吗? - Donghwan Kim
7
是的,HTTP服务器在接收完整个请求之前就发送响应是有效的。不幸的是,没有浏览器会看到早期的响应并停止发送请求,这本身可能违反了RFC 2616 § 8.2.2。 - josh3736
谢谢,知道了很好。 - Donghwan Kim
1个回答

41

查看定义该协议的 RFC 2616,第8.2.2节“监视连接错误状态信息”,其中提到:

在传输请求时,HTTP/1.1(或更高版本)客户端应在监视网络连接是否出现错误状态。如果客户端看到错误状态,则应立即停止传输消息体。

因此,我会建议使用401错误响应。然后查看10.4.2 401 Unauthorized:

请求需要用户身份验证。响应必须包含一个 WWW-Authenticate 头字段(第14.47节),其中包含适用于所请求资源的挑战。客户端可以使用适当的 Authorization 标头字段重试请求。

表示客户端可以使用适当的凭据重试请求。

但我没有进行任何实验来了解浏览器实际上是如何执行的。


11
我测试了这个行为,用于另一个稍微不同的问题,结果不令人满意。所有浏览器在发送请求后才会处理早期响应。 - josh3736
4
RFC指出客户端应该“停止发送请求体”,但是服务器无法知道下一个请求从哪里开始,因此客户端“停止发送请求体”意味着断开连接,因为keep-alive需要知道请求的结束。 - DDS
3
似乎Java的Apache HttpClient不能在服务器未读取完整个请求体时继续运行,这很遗憾 :( 我们遇到了这个问题,当我们没有使用预先认证的HTTP基本身份验证,并且服务器从头信息中已经看出请求无法被允许并立即发送HTTP 401回来。我知道curl和wget可以处理这种情况。我的观点是,所有客户端都应该能够处理这个问题,因为这对于服务器保护自己免受恶意客户端发送大量请求造成的拒绝服务攻击非常重要。 - Kaitsu
3
我也遇到了同样的问题。所有浏览器都无法看到来自服务器的实际响应。它们传输整个内容,然后会将连接视为关闭并重试。如果浏览器没有修复,那么服务器必须进行补偿,并受到接收所有已发送有效载荷的资源影响。如果这样做,就会产生等待数据上传的DDOS攻击的潜在风险。这不太好。浏览器需要支持规范。 - Craig
2
我反过来体验了Java的Apache HttpClient的异步版本,发现即使没有错误状态存在,当请求仍在发送时,该版本确实会在早期响应时停止发送。 - Tuomas Kiviaho
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接