Quelle est la fonction de l'en-tête HTTP «Vary: Accept»?

93

J'utilise PHP pour générer des pages Web dynamiques. Comme indiqué dans le tutoriel suivant (voir le lien ci-dessous), le type MIME des documents XHTML doit être "application / xhtml + xml" lorsque $ _SERVER ['HTTP_ACCEPT'] le permet. Puisque vous pouvez servir la même page avec 2 MIME différents ("application / xhtml + xml" et "text / html"), vous devez définir l'en-tête HTTP "Vary" sur "Accept". Cela aidera le cache sur les proxys.

Lien: http://keystonewebsites.com/articles/mime_type.php

Maintenant, je ne suis pas sûr de l'implication de: header ('Vary: Accept'); Je ne suis pas vraiment sûr de ce que fera exactement «Vary: Accept» ...

La seule explication que j'ai trouvée est:

Après l'en-tête Content-Type, un en-tête Vary est envoyé (si je comprends bien) pour indiquer aux caches intermédiaires, comme les serveurs proxy, que le type de contenu du document varie en fonction des capacités du client qui demande le document. http://www.456bereastreet.com/archive/200408/content_negotiation/

N'importe qui peut me donner une explication "réelle" de cet en-tête ( avec cette valeur ). Je pense que je comprends des choses comme: Vary: Accept-Encoding où le cache sur les proxies pourrait être basé sur le codage de la page servie, mais je ne comprends pas: Vary: Accept

AlexV
la source
1
Franchement - ne vous inquiétez pas. En laissant de côté les failles de la mise en œuvre sur ce site, le seul moment où vous obtiendrez des avantages de servir avec un type de contenu XML, c'est lorsque vous faites des choses qui ne peuvent pas être faites en texte / html - et si tout ce que vous faites est de changer le Doctype et xmlns, alors vous n'allez pas faire ces choses. Tenez-vous-en au texte / html. Pour cette question, vous pouvez aussi bien vous en tenir à HTML 4.01.
Quentin
Oui, je comprends cela et je pense que des "problèmes" comme celui-ci se posent trop souvent dans le développement Web. Merci à "devrait" dans les spécifications / RFC!
AlexV
2
Vous devriez probablement lire ceci: blogs.msdn.com/ieinternals/archive/2009/06/17 / ... avant d'envisager d'utiliser VARY.
EricLaw
1
Cette vidéo a une bonne explication sur l'en- Vary:tête.
Kannan Mohan

Réponses:

94
  • L'en- cache-controltête est le mécanisme principal d'un serveur HTTP pour indiquer à un proxy de mise en cache la "fraîcheur" d'une réponse. (c'est-à-dire, combien / si longtemps pour stocker la réponse dans le cache)

  • Dans certaines situations, les cache-controldirectives sont insuffisantes. Une discussion du groupe de travail HTTP est archivée ici, décrivant une page qui change uniquement avec la langue. Ce n'est pas le cas d'utilisation correct pour l'en-tête de variation, mais le contexte est précieux pour notre discussion. (Bien que je pense que l'en-tête Vary résoudrait le problème dans ce cas, il existe un meilleur moyen.) À partir de cette page:

Vary est strictement pour les cas où il est désespéré ou excessivement compliqué pour un proxy de répliquer ce que le serveur ferait.

Un exemple artificiel:

Votre serveur HTTP a une grande page de destination. Vous avez deux pages légèrement différentes avec la même URL, selon que l'utilisateur y est déjà allé auparavant. Vous faites la distinction entre les demandes et le «nombre de visites» d'un utilisateur sur la base des cookies. Mais - puisque la page de destination de votre serveur est si grande, vous voulez que les proxys intermédiaires mettent en cache la réponse si possible.

Les en-têtes URL, Last-Modified et Cache-Control sont insuffisants pour donner ces informations à un proxy de mise en cache, mais si vous ajoutez Vary: Cookie, le moteur de cache ajoutera l'en-tête Cookie à ses décisions de mise en cache.

Enfin, pour le petit trafic, les sites Web dynamiques - j'ai toujours trouvé le simple Cache-Control: no-cache, no-storeet Pragma: no-cachesuffisant.

Edit - pour répondre plus précisément à votre question: l'en-tête de requête HTTP «Accepter» définit les types de contenu qu'un client peut traiter. Si vous disposez de deux copies du même contenu à la même URL, ne différant que par Content-Type, alors l'utilisation Vary: Acceptpourrait être appropriée.

Mise à jour du 11 septembre 12:

J'inclus quelques liens qui sont apparus dans les commentaires depuis la publication de ce commentaire. Ce sont tous deux d'excellentes ressources pour des exemples (et des problèmes) du monde réel avec Vary: Accept; Si vous lisez cette réponse, vous devez également lire ces liens.

Le premier, de l'exceptionnel EricLaw, sur le comportement d'Internet Explorer avec l'en-tête Vary et certains des défis qu'il présente aux développeurs: Vary Header empêche la mise en cache dans IE . En bref, IE (pré IE9) ne met pas en cache tout contenu qui utilise l'en-tête Vary car le cache de demande n'inclut pas les en-têtes de requête HTTP. EricLaw (Eric Lawrence dans le monde réel) est un gestionnaire de programme au sein de l'équipe IE.

Le second est d'Eran Medan, et est une discussion en cours sur le comportement inattendu lié à Vary dans Chrome: Backing ne gère pas correctement l'en-tête Vary . C'est lié au comportement d'IE, sauf que les développeurs de Chrome ont adopté une approche différente - bien que cela ne semble pas avoir été un choix délibéré.

JJ
la source
3
Méfiez-vous de cela en conjonction avec le bouton de navigation arrière dans Chrome, il y a une sorte de guerre de flamme sur ce bogue (qui est maintenant wontfix pour une raison quelconque) code.google.com/p/chromium/issues/detail?id=94369
Eran Medan
6
@EranMedan Le bogue Chrome a depuis été corrigé.
59

Vary: Acceptdit simplement que la réponse a été générée en fonction de l'en- Accepttête de la demande. Une demande avec un en- Accepttête différent peut obtenir une réponse différente.

(Vous pouvez voir que le code PHP lié regarde $HTTP_ACCEPT. C'est la valeur de l'en- Accepttête de la requête.)

Pour les caches HTTP, cela signifie que la réponse doit être mise en cache avec un soin particulier. Ce ne sera une correspondance valide que pour les demandes ultérieures avec exactement le même en- Accepttête .

Maintenant, cela n'a d'importance que si la page peut être mise en cache en premier lieu. Par défaut, les pages PHP ne le sont pas. Une page PHP peut marquer la sortie comme pouvant être mise en cache en envoyant certains en-têtes ( Expirespar exemple). Mais si et comment faire cela est une autre question.

Jason Orendorff
la source
est-ce "pourrait obtenir" ou "devrait-il obtenir"?
Pacerier
6
@Pacerier "pourrait obtenir" est correct. Vary: Acceptne signifie pas que chaque Acceptvaleur d'en-tête distincte possible produit une réponse différente et unique. Cela signifie seulement qu'un en- Accepttête différent peut produire une réponse différente.
Jason Orendorff
2

Il y a en fait un nombre important de nouvelles fonctionnalités à venir (et déjà dans Chrome) qui rendent l'en- Varytête extrêmement utile. Par exemple, considérez l' indication client . Lorsqu'il est utilisé avec des images, par exemple, l'indication client permet à un serveur d'optimiser des ressources telles que des images en fonction de:

  • Largeur de l'image
  • Largeur de la fenêtre
  • Type d'encodage pris en charge par le navigateur (pensez WebP)
  • Liaison descendante (essentiellement la vitesse du réseau)

Ainsi, un serveur qui prend en charge ces fonctionnalités définirait l'en- Varytête pour l'indiquer.

Chrome annonce la prise en charge de WebP en définissant "image / webp" dans l'en- Varytête de chaque demande. Ainsi, un serveur peut réécrire une image en tant que WebP si le navigateur le prend en charge, de sorte que le proxy devra vérifier l'en-tête afin de ne pas mettre en cache une image WebP, puis la servir à un navigateur qui ne prend pas en charge WebP. De toute évidence, si votre serveur ne fait pas cela, cela n'a pas d'importance. Donc, comme la réponse du serveur varie sur l'en- Accepttête de la requête, la réponse doit l'inclure afin de ne pas confondre les proxys:

Vary: Accept

Un autre exemple pourrait être la largeur de l'image. Sur un navigateur mobile, l'en- Widthtête peut être assez petit pour une image réactive, par rapport à ce qu'il serait s'il était visualisé à partir d'un navigateur de bureau. Donc, dans ce cas, il Widthserait ajouté à l'en- Varytête pour que le proxy ne cache pas la petite version mobile et la serve aux navigateurs de bureau, ou vice versa. Dans ce cas, l'en-tête peut inclure:

Vary: Accept, Width

Ou dans le cas où un serveur prend en charge toutes les spécifications d'indication client, l'en-tête serait quelque chose comme:

Vary: Accept, DPR, Width, Save-Data, Downlink
Brad Berger
la source