HTTP响应状态码“200 OK”是否保证文档已被生成HTTP请求的机器接收?

46
我有两台机器,A和B。
A向B发送HTTP请求,并要求某些文档。 B回复并发送所请求的文档,并带有200 OK消息,但是机器A抱怨由于网络故障未接收到文档。
HTTP状态码200是否也可以作为确认已接收文档的标志?

3
有些系统只有在验证通过后才会返回响应,而有些系统则会在收到请求后立即发送“OK”(无需查看内容)。 - Stultuske
有些是什么意思?HTTP响应代码是独特的。 - Naveen Suryawanshi
这取决于API设计师。我知道一些开发人员喜欢这种API设计方式。他们只是为每个请求返回200,并在响应体中添加一个额外的字段来指示错误。我看到很多API都返回状态码200。然而,实际上他们的服务器出现了错误,应该返回500(内部错误)。 - Tran Thien Chien
2
@NaveenSuryawanshi 一些应用程序,一些服务器。 - Stultuske
1
@NaveenSuryawanshi HTTP响应代码只是一个更大字符串中的几个文本字节,就这样。我可以写一个返回random.nextInt(500)作为其响应代码的Web服务器,如果我想的话。我可以让它始终返回404,无论什么情况,并返回html,就好像已经接收到了一切 - 这只是文本而已。底线是:你不能相信任何东西。 - corsiKa
显示剩余7条评论
6个回答

99

HTTP 200状态码是否也表示已经接收到文档?

不是的,完全不是。

它甚至不能保证文档已完整传输。

响应代码位于响应流的第一行。服务器可能在发送第一行和响应的最后一个字节之间的任何位置失败或与客户端断开连接。服务器可能甚至不知道发生了这种情况。

事实上,服务器无法知道客户端是否已接收完整(或部分)HTTP响应。 HTTP协议中没有提供确认机制。

现在,您可以在HTTP之上实现一个应用程序协议,其中客户端需要向服务器发送第二个HTTP请求以表示“是的,我已收到文档”。但这将涉及用户浏览器中实现一些“应用程序逻辑”,例如JavaScript。


4
值得注意的是,“是的,我收到了文档”功能也可以在传输层上实现(通常假定使用TCP,但并非总是如此),尽管作为更多的“是的,我收到了你发送给我的所有数据包”的响应。 - Rebecca Nelson
6
除非你做了一些奇怪的事情,HTTP协议使用TCP协议来保证传输并且确实有ACK数据包。监测TCP连接是否过早关闭就足以检查客户端是否已经完整地收到了你的响应。 - Bergi
8
在典型的HTTP服务器端应用程序逻辑(例如Servlet代码)中,通常不会通知应用程序逻辑(例如Servlet代码)如果TCP连接意外关闭。但实际上,这对于服务器来知道客户端已接收到数据的应用程序级别并不足够。如果浏览器关闭,客户端TCP栈可能以无法区分应用程序发起的关闭方式关闭连接。那么还存在代理的问题。 - Stephen C
3
@Bergi - “...但我期望这在每个主要框架中都是可能的。”你有例子来支持这一点吗?因为我的经验是,你所说的并不是真的...至少对于Servlet规范的典型实现而言。 - Stephen C
2
即使是TCP协议也可能"被欺骗"。文档可能已经被代理接收和存储,但客户端可能已经失去与代理的连接。 - Klaws
显示剩余8条评论

13

绝对不行。 HTTP 200 是由服务器生成的,仅表示它理解了请求并认为能够满足请求(例如文件实际上存在)。 传输完整响应文档期间可能发生各种错误(网络连接中断、丢包等),这些错误不会在 HTTP 响应中显示,但需要单独检测。


11

这里有一份关于HTTP协议的相当不错的指南:http://blog.catchpoint.com/2010/09/17/anatomyhttp/

你应该区分HTTP协议和底层流传输协议,后者应该对HTTP目的进行可靠传输。流传输协议将确认所有数据传输,包括响应,以确保交换的双方都确认数据正确传输。如果传输流失败,则会出现“网络故障”或类似错误。当发生这种情况时,HTTP协议无法继续;数据不再可靠甚至不完整。

在HTTP级别上,200 OK消息的意思是服务器具有您要请求的文档并即将向您传输它。通常还会得到一个内容长度头,因此您可以确定何时完成主体作为流协议的附加检查。从HTTP协议的角度来看,响应没有接收到任何确认,因此一旦响应被发送,就没有验证。

然而,由于流传输是可靠的,发送响应的行为将成功或导致错误。这确实验证了文档是否已被网络目标接收(如TripeHound所述,在非直接连接的情况下,例如代理,这不能保证传递到最终目标)。


如果涉及到代理,这将验证文档是否已被接收,但不一定是最终目标。 - TripeHound
您的URL已失效,错误代码503,后端没有可用的健康IP。 - The Segfault

7
很明显,200 OK响应代码无法保证响应文档的任何内容。它是在文档被传输发送的,因此只有违反因果关系才能使其依赖于成功接收文档。它只用作指示请求是否正确接收以及服务器是否能够满足请求的指标。如果请求需要额外处理(例如运行脚本),而不仅仅返回静态文档,则响应代码通常应在完成此操作后发送,因此通常表示此操作成功(但在存在持久连接和推送通知等情况下可能不可行,因为脚本可能稍后失败)。
更一般地说,在任何协议中都无法提供所有消息已被接收的绝对保证,这是由于“两将军问题”。没有确认系统可以解决这个问题,因为在某些时候必须有最后的确认,而我们无法知道这是否被成功接收,因为这将需要另一个确认,与它是最后一个确认的前提相矛盾。

4

HTTP的设计考虑了各种"中间盒子"的可能性,这些代理能够在客户端知道或不知情的情况下进行操作。

如果有代理参与,则即使知道服务器传输了所有数据并收到了正常的关闭连接,也无法确定文档是否已被生成HTTP请求的机器接收。


-4

A向B发送请求。在请求到达B之前,可能会有各种障碍阻止请求到达B。在https的情况下,请求可能已经到达B,但被拒绝,并且它将被视为未到达B。在所有这些情况下,B都不会发送任何状态。

一旦请求到达B,并且没有崩溃B的错误和硬件故障等问题,B将检查请求并确定要做什么以及要报告什么状态。如果A请求的文件存在并且A被允许访问,则B将开始发送“状态200”以及文件数据。

同样,各种事情都可能出错。A可能什么也没收到,或者收到了没有数据或不完整数据的“状态200”等。(通过“接收”,我指的是数据通过以太网电缆或WiFi到达)。

通常,A的用户将使用某个处理不良部分的库。使用一些体面的库,用户可以期望他们要么得到一些错误,要么得到一个带有相应数据的状态。如果状态200带有只有一半数据的到达A,用户将(根据库的设计)收到一个错误,而不是状态,绝对不是状态200。

或者你可能有一个库报告状态200并告诉你“这是前2000个字节”,“这是接下来的2000个字节”等等,当出现问题时,你可能会被告知“抱歉,发生了错误,数据不完整”。

但一般情况下,用户得到状态200但没有数据的情况是不会发生的。


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