46

I have two machines, A and B.

A sends an HTTP request to B and asks for some document. B responds back and sends the requested document and gives a 200 OK message, but machine A is complaining that the document is not received because of a network failure.

Does HTTP code 200 also work as acknowledgment that the document is received?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Naveen Suryawanshi
  • 513
  • 1
  • 4
  • 15
  • 3
    depends. some only return a response if everything is validated, some immediately send an "OK" if the request is received (without looking at the contents) – Stultuske Mar 15 '18 at 07:38
  • Some means what? HTTP response code is unique. – Naveen Suryawanshi Mar 15 '18 at 07:41
  • It up to the API designer. I know some developers who prefer this way of designing APIs. They just return 200 for every request and add one more additional field on response body to indicate the error. I've been seeing many APIs give status 200. However there is actually an error on their server where they should return 500(internal error). – Tran Thien Chien Mar 15 '18 at 07:44
  • 2
    @NaveenSuryawanshi some applications, some servers. – Stultuske Mar 15 '18 at 07:47
  • In your case, what is the really important thing: Is it that the server detects when a document has definitely been completely transmitted, or that a document has definitely NOT been transmitted? In other words, is it a major problem if the server thinks the document was not received even though it was? Is ok if the server just sends the same document again on a retry request, if necessary? The answer to that question drastically changes the solution to the problem. – LordOfThePigs Mar 15 '18 at 13:05
  • This deserves a better answer, but in order to provide a better answer, you need to provide why you are asking the question. Hint: last byte received by client is something you could theoretically know but turns out to be not what you actually want to know. – Joshua Mar 15 '18 at 15:33
  • I once saw a web site that returned a 403 status code for its normal pages, and 200 for its "page not found" pages. Someone apparently got something backwards. Ultimately, the only thing a 200 guarantees is that the last server, in the possibly-long chain of servers that you talked to, returned 200. – yshavit Mar 15 '18 at 19:25
  • 1
    @NaveenSuryawanshi HTTP response code is just a couple bytes of text in a bigger string of text. That's literally it. I can write a webserver that returns `random.nextInt(500)` as its response code if I want. I could have it always return `404` no matter what, and return the `html` as if everything was received - it's just text. Bottom line, you can't trust anything. – corsiKa Mar 15 '18 at 23:16
  • @Stultuske and corsiKa have some very good points incase they're hidden by the show more comments button/link – brandito Mar 16 '18 at 03:57
  • Note that the general case of this is called the Two Generals problem, and it's been proved to be impossible for you know that the server has received the document OK and for the server to know that you've received an acknowledgement. One or the other can be done, but not both. https://en.wikipedia.org/wiki/Two_Generals%27_Problem – Mike Scott Mar 16 '18 at 12:33
  • The server `B` could simply be sending 200 OK but wrong content length. This _should_ cause `A` to complain about missing data. – Salman A Mar 20 '18 at 12:58
  • The status code 200 OK only means your request has succeeded. If you requested a file then the server sends it to you with the status code. Whether you get it or not does is not said in the status code. check this https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html – landrykapela Mar 21 '18 at 08:04

6 Answers6

99

Does the HTTP 200 code also work as an acknowledgment that document has been received?

No. Not at all.

It is not even a guarantee that the document was completely transmitted.

The response code is in the first line of the response stream. The server could fail, or be disconnected from the client anywhere between sending the first line and the last byte of the response. The server may not even know this has happened.

In fact, there is no way that the server can know if the client received a complete (or partial) HTTP response. There is no provision for an acknowledgment in the HTTP protocol.

Now you could implement an application protocol over the top of HTTP in which the client is required to send a second HTTP request to the server to say "yes, I got the document". But this would involve some "application logic" implemented in the user's browser; e.g. in Javascript.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 4
    Also worth noting is that this "yes, I got the document" functionality can be implemented on the transport layer as well (and very often is, assuming TCP is used- but this is not always the case), albeit as more of a "yes, I received all the packets you sent me" response. – Rebecca Nelson Mar 15 '18 at 10:43
  • 6
    Uh, unless you [do something weird](https://stackoverflow.com/a/323380/1048572), HTTP uses TCP which guarantees transmission and *does* have ACK packets. Monitoring whether the TCP connection is prematurely closed will suffice to check that the client got your complete response. – Bergi Mar 15 '18 at 10:59
  • 8
    @Bergi - In a typical HTTP server-side, the application logic (e.g. the Servlet code) typically doesn't get informed if the TCP connection closes prematurely. But actually, that is not sufficient for the server to know that the application level of the client has received the data. If the browser is closed, the client-side TCP stack may close the connection in a way that is indistinguishable from an application initiated close. Then there is the problem of proxies. – Stephen C Mar 15 '18 at 11:07
  • 1
    @StephenC I don't know what a "typical HTTP server" looks like, but I would expect this to be possible in every major framework. Of course usually you don't need this so if you do you need to explicitly opt into it. And yes, the client having received the data of course doesn't mean that it has correctly or completely processed them, you can never ensure that. – Bergi Mar 15 '18 at 11:22
  • 3
    @Bergi - *" ... but I would expect this to be possible in every major framework."*. Do you have examples to back this up? Because my *experience* is that what you are saying is not true ... at least for a *typical* implementation of the Servlet specs. – Stephen C Mar 15 '18 at 11:34
  • Well, the application logic could just be using the standard `Content-Length` HTTP header. If the length of the received body matches the length specified in `Content-Length`, then the client know that it has received the whole document. Most web servers will set that header correctly when serving static content. Whether or not it is set the OP's case really depends on his whole setup. – LordOfThePigs Mar 15 '18 at 12:55
  • 1
    Yes. But the problem is that it is **the server** that needs to know if the client has received the document. (And there is the small problem of documents getting corrupted in transit. To which there are solutions ... but it is more complicated than just checking `Content-Length`.) – Stephen C Mar 15 '18 at 12:59
  • 1
    @StephenC fair enough, I missed the part where it is the server who needs to know if the client has received it. – LordOfThePigs Mar 15 '18 at 13:01
  • 2
    Well, even TCP can be "fooled". The document may have been received and stored by a proxy, but the client may have lost the connection to the proxy. – Klaws Mar 15 '18 at 14:48
  • @StephenC OK, I have no experience with Java Servlets, but e.g. in Node.js it is trivial to access the [request's](https://nodejs.org/api/http.html#http_request_socket)/[response's socket](https://nodejs.org/api/http.html#http_response_socket) and listen to its events. – Bergi Mar 15 '18 at 16:00
  • I cannot tell for Java - it might not have it - But ASP.NET has a handy api to check if the connection to client failed in the form of [ClientDisconnectedToken](https://msdn.microsoft.com/en-us/library/system.web.httpresponse.clientdisconnectedtoken.aspx). PHP, on the other hand, by default abort the server script. However you can set [ignore_user_abort](https://secure.php.net/manual/en/function.ignore-user-abort.php) and check [connection_status](https://secure.php.net/manual/en/function.connection-status.php). – Theraot Mar 16 '18 at 08:28
  • Those things in Node.js, ASP.NET and PHP will tell you that a connection *definitely* failed before the response was fully delivered. But they don't / can't tell you if it *definitely* succeeded. For a start .... possible web browser bugs. – Stephen C Dec 08 '18 at 07:58
  • @StephenC To back you up, the TCP acknowledgements don't mean anything to the server application that it cannot tell you for sure if the data is loaded into the client application's buffer. – Charlie May 15 '19 at 03:22
13

Absolutely not. HTTP 200 is generated by the server, and only means that it understood the request and thinks it is able to fulfill it (e.g. the file is actually there). All sorts of errors may occur during the transmission of the full response document (network connection breaking, packet loss, etc) which will not show up in the HTTP response, but need to be detected separately.

WooShell
  • 230
  • 1
  • 6
11

A pretty good guide to the HTTP protocol is found here: http://blog.catchpoint.com/2010/09/17/anatomyhttp/

You should make a distinction between the HTTP protocol and the underlying stream transport protocol, which should be reliable for HTTP purposes. The stream transport protocol will ACKnowledge all data transmission, including the response, so that both ends of exchange will affirm that the data is transmitted correctly. If the transport stream fails, then you will get a 'network failure' or similar error. When this happens, the HTTP protocol cannot continue; the data is no longer reliable or even complete.

What a 200 OK message means, at the HTTP level, is that the server has the document you're after and is about to transmit it to you. Normally you will get a content-length header as well, so you will be able to ascertain if/when the body is complete as an additional check on top of the stream protocol. From the HTTP protocol perspective, a response receives no acknowledgement, so once a response has been sent there is no verification.

However, as the stream transport is reliable, the act of sending the response will either be successful or result in an error. This does verify whether the document has been received by the network target (as noted by TripeHound, in the case of non-direct connection, e.g. a proxy, this is not a guarantee of delivery to the final target).

Danikov
  • 735
  • 3
  • 10
  • "_This does verify whether the document has been received by the target_" or by _something_ if there are proxies involved... not necessarily the final target. – TripeHound Mar 15 '18 at 16:58
  • You url is dead Error 503 No healthy IP available for the backend – The Segfault Sep 05 '22 at 05:18
7

It's very simple to see that the 200 OK response code can't be a guarantee of anything about the response document. It's sent before the document is transmitted, so only a violation of causality could allow it to be dependent on successful reception of the document. It only serves as an indicator that the request was received properly and the server believes that it's able to fulfill the request. If the request requires extra processing (e.g. running a script), rather than just returning a static document, the response code should generally be sent after this has been completed, so it's normally an indicator that this was successful (but there are situations where this is not feasible, such as requests with persistent connections and push notifications -- the script could fail later).

On a more general level, it's never possible to provide an absolute guarantee that all messages have been received in any protocol, due to the Two Generals Problem. No acknowledgement system can get around this, because at some point there has to be a last acknowledgement; there's no way to know if this is received successfully, because that would require another acknowledgement, contradicting the premise that it was the last one.

Barmar
  • 741,623
  • 53
  • 500
  • 612
4

HTTP is designed with an awareness of the possibility of various sorts of "middleboxes" - proxies operating with or without the knowledge of the client.

If there is a proxy involved, then even knowing that the server had transmitted all the data and recieved an normal close connection would not tell you anything about whether the document has been received by the machine who generated the HTTP request.

pjc50
  • 1,856
  • 16
  • 18
-4

A sends a request to B. There may be all kinds of obstacles in the way that prevent the request from reaching B. In the case of https, the request may be reaching B but be rejected and it counts as if it hadn't reached B. In all these cases, B will not send any status at all.

Once the request reaches B, and there are no bugs crashing B, and no hardware failure etc. B will examine the request and determine what to do and what status to report. If A requested a file that is there and A is allowed access, B will start sending a "status 200" together with the file data.

Again all kinds of things can go wrong. A may receive nothing, or the "status 200" with no data or incomplete data etc. (By "receive" I mean that data arrives on the Ethernet cable, or through WiFi).

Usually the user of A will use some library that handles the ugly bits. With some decent library, the user can expect that they either get some error, or a status complete with the corresponding data. If a status 200 arrives at A with only half the data, the user will (depending on the design of the library) receive an error, not a status, and definitely not a status 200.

Or you may have a library that reports the status 200 and tells you "here's the first 2,000 bytes", "here's the next 2,000 bytes" and so on, and at some point when things go wrong, you might be told "sorry, there was an error, the data is incomplete".

But in general, the case that the user gets a status 200, and no data, will not happen.

gnasher729
  • 51,477
  • 5
  • 75
  • 98