How to interpret “Connection: keep-alive, close”?

2019-02-01 18:19发布

问题:

From what I understand, a HTTP connection could either be keep-alive or close.

I sent a HTTP request to a server:

GET /page1/ HTTP/1.1
Host: server.com
Connection: keep-alive

And it responded with:

HTTP/1.1 200 OK
Connection: keep-alive, close

Essentially, I believe the server is bugged because a response like keep-alive, close is ambiguous.

However, as the receiver, how should we handle such a message? Should we interpret this header value as keep-alive or close?

回答1:

TL; DR: Chrome interprets this response header as keep-alive and maintain a peristent connection while Firefox closes each connection.

I stumbled over this question as I tried to optimize the page loading time for my website.

In the referenced RFC I didn't find anything about how multiple entries in the Connection header may be properly handled. It seemed to me like the implementation may choose from two possibilites:

  1. If there are multiple entries, you may choose that fits best to your needs
  2. If there is a close inside, you may close the connection after transmission

So, I needed to find out. Let's make some deeper investigation:

I noticed that Chrome was always sending a HTTP/1.1 request with Connection: keep-alive and my Apache default configuration was always responding with a Connection: close header. So I began investigating and took a look at the TCP segments with Wireshark.

Chrome has to fetch 14 elements to display the website, mostly of them static things like images or css files. And it took in complete 14 TCP connections and that took a lot of time (approximately 1,2 seconds). After each request for an image (e.g.) there came a TCP segment with the FIN flag set to 1.

So what about Chrome vs. Firefox? Chrome seems to have a maximum number of concurrent connections to one server of 6. Firefox has a more granular configuration and distinguishs persistent (maxium of 6, seen in about:config) and non-persistent (the maximum numbers differed a lot in different sources). But wait... Both, Chrome and Firefox are sending HTTP/1.1 request headers with Connection: keep-alive, so both should be limited to 6 (as this is a request for opening up a persistent connection).

I decided to try a simple trick and added the following lines to my .htaccess in the web root folder:

<ifModule mod_headers.c>
Header set Connection keep-alive
</ifModule>

The server now responds with:

Connection: keep-alive, close

Now I took a look at the TCP segments again: There were only 9 connections from Chrome to my server now and only 3 with the FIN flag set to 1. So this trick seemed to work. But why were there those 3 connections, that closed the connection after data transmission? These were the PHP requests, as the HTTP header X-Powered-By: PHP/5.4.11 confirmed.

And what about Firefox? There were still those 14 requests!

How to fix that and get the fcgi processes to work with keep-alive too?

I added the following lines to my virtualhost section of the httpd.conf configuration:

KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100

and removed the ones added in the .htaccess. Now the server isn't sending any confusing - Connection: keep-alive, close, but only Connection: keep-alive and everything works fine!

Conclusion:

A header with the connection field set to

HTTP/1.1 200 OK
Connection: keep-alive, close

will be interpreted by Chrome as keep-alive while Firefox seems to close each connection. It seems to depend on the actual implementation.

So if you're willing to implement a client for handling response headers that contain Connection: keep-alive, close, I would propose to try using keep-alive if you need more than one request. The worst thing that may happen: The server will close the connection and you need to connect again (that's exactly the other option you would have had!)



回答2:

It means that the server won't do persistent connections and will close the connection after this request.



回答3:

The answer is at RFC 7230 — 6.1. Connection. It says:

The Connection header field's value has the following grammar:

 Connection        = 1#connection-option
 connection-option = token

In Internet RFC parlance, the 1#connection-option means at least one and at most any number of connection-option. This means there may be multiple options among which the receiver will pick anyone it prefers. That's not an ambiguity, that's a choice.



回答4:

You are using HTTP/1.1 and you are specifying Connection: keep-alive.

Under HTTP/1.1 all connections are keep-alive by default, and the Connection: keep-alive header has been deprecated, so you should not send it.

Connection: keep-alive is a little hack used back in the so-called HTTP/1.0+ days. (The + stands for "hacks necessary to get it to work.")

In HTTP: The Definitive Guide by Brian Totty, Marjorie Sayer, Sailu Reddy, Anshu Aggarwal, David Gourley by O'Reilly we read:

Keep-alive is deprecated and no longer documented in the current HTTP/1.1 specification. However, keep-alive handshaking is still in relatively common use by browsers and servers, so HTTP implementors should be prepared to interoperate with it.

The server might be "interoperating" and trolling you for being redundant.