web-dev-qa-db-fra.com

Comment interpréter "Connection: keep-alive, close"?

D'après ce que je comprends, une connexion HTTP pourrait être keep-alive ou close.

J'ai envoyé une requête HTTP à un serveur:

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

Et il a répondu:

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

Essentiellement, je crois que le serveur est buggé car une réponse comme keep-alive, close c'est ambigu.

Cependant, en tant que récepteur, comment devrions-nous gérer un tel message? Devrions-nous interpréter cette valeur d'en-tête comme keep-alive ou close?

34
Pacerier

TL; DR: Chrome interprète cet en-tête de réponse comme keep-alive et maintenir une connexion permanente tandis que Firefox ferme chaque connexion.

Je suis tombé sur cette question en essayant d'optimiser le temps de chargement des pages pour mon site Web.

Dans la RFC référencée, je n'ai rien trouvé sur la façon dont plusieurs entrées dans l'en-tête Connection peuvent être correctement gérées. Il m'a semblé que la mise en œuvre pouvait choisir entre deux possibilités:

  1. S'il y a plusieurs entrées, vous pouvez choisir celle qui correspond le mieux à vos besoins
  2. S'il y a un close à l'intérieur, vous pouvez fermer la connexion après la transmission

Donc, je devais le découvrir. Faisons une enquête plus approfondie:

J'ai remarqué que Chrome envoyait toujours une demande HTTP/1.1 avec Connection: keep-alive et ma configuration par défaut d'Apache répondait toujours par un Connection: close entête. J'ai donc commencé à enquêter et j'ai regardé les segments TCP avec Wireshark.

Chrome doit récupérer 14 éléments pour afficher le site Web, principalement des éléments statiques comme des images ou des fichiers CSS. Et cela a pris 14 TCP et cela a pris beaucoup de temps (environ 1,2 seconde). Après chaque demande d'image (par exemple), il y avait un TCP avec l'indicateur FIN défini sur 1.

Alors qu'en est-il de Chrome vs Firefox? Chrome semble avoir un nombre maximum de connexions simultanées à un serveur de 6. Firefox a une configuration plus granulaire et distingue persistant (maxium de 6, vu dans about: config) et non persistant (les nombres maximum diffèrent beaucoup selon les sources). Mais attendez ... Les deux, Chrome et Firefox envoient HTTP /1.1 en-têtes de demande avec Connection: keep-alive, les deux devraient donc être limités à 6 (car il s'agit d'une demande d'ouverture d'une connexion persistante).

J'ai décidé d'essayer une astuce simple et j'ai ajouté les lignes suivantes à mon .htaccess dans le dossier racine Web:

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

Le serveur répond maintenant avec:

Connection: keep-alive, close

Maintenant, j'ai jeté un coup d'œil aux segments TCP à nouveau: il n'y avait que 9 connexions de Chrome à mon serveur maintenant et seulement 3 avec le FIN flag mis à 1. Donc, cette astuce semblait fonctionner. Mais pourquoi y avait-il ces 3 connexions, qui ont fermé la connexion après la transmission des données? Ce sont les requêtes PHP, comme en-tête HTTP X-Powered-By: PHP/5.4.11 confirmé.

Et qu'en est-il de Firefox? Il y avait encore ces 14 demandes!

Comment résoudre ce problème et faire fonctionner les processus fcgi avec keep-alive aussi?

J'ai ajouté les lignes suivantes à ma section virtualhost de la configuration httpd.conf:

KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100

et supprimé ceux ajoutés dans le .htaccess. Maintenant, le serveur n'envoie pas de confusion - Connection: keep-alive, close, mais, seulement Connection: keep-alive et tout fonctionne bien!

Conclusion:

Un en-tête avec le champ de connexion défini sur

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

sera interprété par Chrome comme keep-alive tandis que Firefox semble fermer chaque connexion. Cela semble dépendre de la mise en œuvre réelle.

Donc, si vous êtes prêt à implémenter un client pour gérer les en-têtes de réponse contenant Connection: keep-alive, close, Je proposerais d'essayer d'utiliser keep-alive si vous avez besoin de plusieurs requêtes. La pire chose qui puisse arriver: le serveur fermera la connexion et vous devez vous reconnecter (c'est exactement l'autre option que vous auriez eue!)

26

Cela signifie que le serveur ne fera pas de connexions persistantes et fermera la connexion après cette demande.

3
jman

Vous utilisez HTTP/1.1 et vous spécifiez Connection: keep-alive.

En dessous de HTTP/1.1 toutes les connexions sont maintenues par défaut, et le Connection: keep-alive l'en-tête est obsolète, vous ne devez donc pas l'envoyer.

Connection: keep-alive est un petit hack utilisé dans le soi-disant HTTP/1.0+ journées. (Le + signifie "hacks nécessaires pour le faire fonctionner.")

Dans HTTP: The Definitive Guide de Brian Totty, Marjorie Sayer, Sailu Reddy, Anshu Aggarwal, David Gourley par O'Reilly nous lisons:

Keep-alive est déconseillé et n'est plus documenté dans la spécification HTTP/1.1 actuelle. Cependant, la prise de contact permanente est toujours relativement utilisée par les navigateurs et les serveurs, donc les implémenteurs HTTP doivent être prêts à interagir avec elle.

Le serveur peut être "interopérant" et vous trolling pour être redondant.

2
Mike Nakis

La réponse est à RFC 7230 - 6.1. Connexion . Ça dit:

La valeur du champ d'en-tête Connection a la grammaire suivante:

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

Dans le langage Internet RFC, le 1#connection-option signifie au moins un et au plus n'importe quel nombre de connection-option. Cela signifie qu'il peut y avoir plusieurs options parmi lesquelles le récepteur choisira celui qu'il préfère. Ce n'est pas une ambiguïté, c'est un choix.

2
Hibou57