23

There exists a known race condition in the HTTP keepalive mechanism:

As I understand, I need my HTTP client either to have a shorter timeout than my HTTP server, or retry when getting TCP-FIN or TCP-RST.

My question is, how do today's web-browsers, that use the HTTP keepalive feature, handle this race condition. Do they retry?

I'll be happy for references, a google search hasn't come up with anything.

Community
  • 1
  • 1
speller
  • 1,641
  • 2
  • 20
  • 27

1 Answers1

21

According the the RFC, in these cases, a server should respond with a 408 error code, signalling to the client that the connection has already been closed on its side. As the RFC states:

If the client has an outstanding request in transit, the client MAY repeat that request on a new connection.

This means that it's up to the client (aka each browser) to decide how a 408 response will be handled. There are 2 alternatives:

  • handle it gracefully: retrying the remaining requests in a new connection automatically, so that the user stays completely unaware of the underlying failure that happened
  • fail-fast: showing the user a failure with the appropriate 408 error message

For example, it seems that Chrome in the past was following the second approach until a point, where people started considering this as a "buggy" behaviour and switched to the first one. You can find the bug thread related to the Chromium bug here and the associated code change here.

Note: As you can read in the final emails in the linked thread, Chrome performs these retries, only when some requests have succeeded in this connection. As a result, if you try to reproduce that with a single request, returning a 408 response, you'll notice that Chrome won't probably retry in that case.

Community
  • 1
  • 1
Dimos
  • 8,330
  • 1
  • 38
  • 37
  • Thank you for taking the time and researching this. – Georg Schölly Oct 04 '17 at 09:05
  • 408 response code is for request timeout - the scenario when a client has started sending the request and is not sending it fast enough. In Keepalive race, the server closes the connection when a connection has been idle for a while and there are no in-flight requests which the server can see so it cannot send a 408 response to the client. – avmohan May 03 '18 at 14:41
  • 1
    @avmohan I don't think that's correct. A server will respond with a 408, even when the client has opened the connection and sent no packet at all. For instance, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408 – Dimos May 03 '18 at 19:44
  • Thanks for the reference, Dimos. I had no idea that there could be a response without a request. Good to know. I've seen these race conditions between Apache httpd as a reverse proxy and tomcat. Tomcat closes a persistent connection (without sending a 408) and at the same time httpd forwards a request from client resulting in a 502 error to the client. The only way we could fix these was to keep the idle timeout on httpd lower than tomcat. – avmohan May 04 '18 at 00:17