Aller au contenu principal

13. Caching in HTTP (Mise en Cache dans HTTP)

13 Caching in HTTP

HTTP est généralement utilisé pour des systèmes d'information distribués, où les performances peuvent être améliorées par l'usage de caches de réponses. Le protocole HTTP/1.1 comprend un certain nombre d'éléments destinés à faire fonctionner la mise en cache aussi bien que possible. Comme ces éléments sont indissociables des autres aspects du protocole, et comme ils interagissent les uns avec les autres, il est utile de décrire la conception de base de la mise en cache de HTTP séparément des descriptions détaillées des méthodes, des en-têtes, des codes de réponse, etc.

La mise en cache serait inutile si elle n'améliorait pas sensiblement les performances. L'objectif de la mise en cache dans HTTP/1.1 est d'éliminer la nécessité d'envoyer des requêtes dans de nombreux cas, et d'éliminer la nécessité d'envoyer des réponses complètes dans beaucoup d'autres cas. Le premier réduit le nombre d'allers-retours réseau requis par de nombreuses opérations ; nous utilisons pour cela un mécanisme "d'expiration" (voir la section 13.2). Le second réduit les besoins en bande passante réseau ; nous utilisons pour cela un mécanisme de "validation" (voir la section 13.3).

Les exigences de performances, de disponibilité et de fonctionnement hors connexion nous obligent à pouvoir relâcher l'objectif de transparence sémantique. Le protocole HTTP/1.1 permet aux serveurs d'origine, aux caches et aux clients de réduire explicitement la transparence lorsque c'est nécessaire. Toutefois, comme un fonctionnement non transparent peut dérouter les utilisateurs non avertis, et peut être incompatible avec certaines applications serveur (comme celles servant à commander des marchandises), le protocole exige que la transparence ne soit relâchée

  - que par une requête explicite au niveau du protocole, lorsqu'elle est relâchée par le client ou le serveur d'origine

- qu'avec un avertissement explicite à l'utilisateur final, lorsqu'elle est relâchée par le cache ou le client

Par conséquent, le protocole HTTP/1.1 fournit ces éléments importants :

  1. Des fonctionnalités de protocole qui assurent une transparence sémantique complète lorsque toutes les parties l'exigent.

2. Des fonctionnalités de protocole qui permettent à un serveur d'origine ou à un agent utilisateur de demander et de contrôler explicitement un fonctionnement non transparent.

3. Des fonctionnalités de protocole qui permettent à un cache d'attacher des avertissements aux réponses qui ne préservent pas l'approximation demandée de la transparence sémantique.

Un principe de base est qu'il doit être possible aux clients de détecter tout relâchement potentiel de la transparence sémantique.

  Note: L'implémenteur du serveur, du cache ou du client peut être confronté à des décisions de conception qui ne sont pas explicitement abordées dans cette spécification. Si une décision peut affecter la transparence sémantique, l'implémenteur devrait pencher vers le maintien de la transparence, à moins qu'une analyse attentive et complète ne montre des avantages significatifs à la rompre.

13.1.1 Cache Correctness (Exactitude du Cache)​

Un cache correct doit (MUST) répondre à une requête avec la réponse la plus à jour détenue par le cache qui soit appropriée à la requête (voir les sections 13.2.5, 13.2.6 et 13.12) et qui satisfasse l'une des conditions suivantes :

  1. Elle a été vérifiée quant à son équivalence avec ce que le serveur d'origine aurait renvoyé, en revalidant la réponse auprès du serveur d'origine (section 13.3) ;

2. Elle est "suffisamment fraîche" (voir la section 13.2). Dans le cas par défaut, cela signifie qu'elle satisfait l'exigence de fraîcheur la moins restrictive du client, du serveur d'origine et du cache (voir la section 14.9) ; si le serveur d'origine le précise ainsi, il s'agit de la seule exigence de fraîcheur du serveur d'origine.

Si une réponse stockée n'est pas "suffisamment fraîche" selon l'exigence de fraîcheur la plus restrictive à la fois du client et du serveur d'origine, dans des circonstances soigneusement pesées, le cache peut (MAY) tout de même renvoyer la réponse avec l'en-tête Warning approprié (voir les sections 13.1.5 et 14.46), à moins qu'une telle réponse soit interdite (par exemple par une cache-directive "no-store" ou par une cache-request-directive "no-cache" ; voir la section 14.9).

3. Il s'agit d'un message de réponse approprié 304 (Not Modified), 305 (Proxy Redirect) ou d'erreur (4xx ou 5xx).

Si le cache ne peut pas communiquer avec le serveur d'origine, un cache correct devrait (SHOULD) répondre comme ci-dessus si la réponse peut être correctement servie depuis le cache ; sinon il doit (MUST) renvoyer une erreur ou un avertissement indiquant qu'il y a eu une défaillance de communication.

Si un cache reçoit une réponse (soit une réponse entière, soit une réponse 304 (Not Modified)) qu'il transmettrait normalement au client demandeur, et que la réponse reçue n'est plus fraîche, le cache devrait (SHOULD) la transmettre au client demandeur sans ajouter de nouvel avertissement (mais sans supprimer aucun en-tête Warning existant). Un cache ne devrait pas (SHOULD NOT) tenter de revalider une réponse simplement parce que cette réponse est devenue périmée en transit ; cela pourrait conduire à une boucle infinie. Un agent utilisateur qui reçoit une réponse périmée sans avertissement peut (MAY) afficher une indication d'avertissement à l'utilisateur.

13.1.2 Warnings (Avertissements)​

Chaque fois qu'un cache renvoie une réponse qui n'est ni de première main ni "suffisamment fraîche" (au sens de la condition 2 de la section 13.1.1), il doit (MUST) attacher un avertissement à cet effet, en utilisant un en-tête général Warning. L'en-tête Warning et les avertissements actuellement définis sont décrits à la section 14.46. L'avertissement permet aux clients de prendre les mesures appropriées.

Les avertissements peuvent (MAY) être utilisés à d'autres fins, tant liées au cache que non. L'usage d'un avertissement, plutôt que d'un code de statut d'erreur, distingue ces réponses des véritables défaillances.

Des codes d'avertissement à trois chiffres sont attribués aux avertissements. Le premier chiffre indique si l'en-tête Warning doit (MUST) ou ne doit pas (MUST NOT) être supprimé d'une entrée de cache stockée après une revalidation réussie :

1xx Avertissements qui décrivent la fraîcheur ou l'état de revalidation de la réponse, et qui doivent (MUST) donc être supprimés après une revalidation réussie. Les warn-codes 1xx peuvent (MAY) être générés par un cache uniquement lors de la validation d'une entrée mise en cache. Ils ne doivent pas (MUST NOT) être générés par les clients.

2xx Avertissements qui décrivent un aspect du corps d'entité ou des en-têtes d'entité que ne corrige pas une revalidation (par exemple une compression avec perte des corps d'entité) et qui ne doivent pas (MUST NOT) être supprimés après une revalidation réussie.

Voir la section 14.46 pour les définitions des codes eux-mêmes.

Les caches HTTP/1.0 mettront en cache tous les avertissements des réponses, sans supprimer ceux de la première catégorie. Les avertissements des réponses qui sont transmises à des caches HTTP/1.0 portent un champ warning-date supplémentaire, ce qui évite qu'un futur destinataire HTTP/1.1 ne croie à un avertissement mis en cache par erreur.

Les avertissements portent également un texte d'avertissement. Le texte peut (MAY) être dans toute langue naturelle appropriée (peut-être en fonction des en-têtes Accept du client), et inclure une indication OPTIONAL du jeu de caractères utilisé.

Plusieurs avertissements peuvent (MAY) être attachés à une réponse (soit par le serveur d'origine, soit par un cache), y compris plusieurs avertissements ayant le même numéro de code. Par exemple, un serveur pourrait fournir le même avertissement avec des textes en anglais et en basque.

Lorsque plusieurs avertissements sont attachés à une réponse, il peut ne pas être pratique ou raisonnable de les afficher tous à l'utilisateur. Cette version de HTTP ne spécifie pas de règles de priorité strictes pour décider quels avertissements afficher et dans quel ordre, mais suggère quelques heuristiques.

13.1.3 Cache-control Mechanisms (Mécanismes de Contrôle du Cache)​

Les mécanismes de base de la mise en cache dans HTTP/1.1 (temps d'expiration et validateurs spécifiés par le serveur) sont des directives implicites adressées aux caches. Dans certains cas, un serveur ou un client peut avoir besoin de fournir des directives explicites aux caches HTTP. Nous utilisons pour cela l'en-tête Cache-Control.

L'en-tête Cache-Control permet à un client ou à un serveur de transmettre diverses directives dans des requêtes ou des réponses. Ces directives remplacent généralement les algorithmes de mise en cache par défaut. En règle générale, s'il existe un conflit apparent entre des valeurs d'en-tête, c'est l'interprétation la plus restrictive qui s'applique (c'est-à-dire celle qui est la plus susceptible de préserver la transparence sémantique). Toutefois, dans certains cas, des directives cache-control sont explicitement spécifiées comme affaiblissant l'approximation de la transparence sémantique (par exemple "max-stale" ou "public").

Les directives cache-control sont décrites en détail à la section 14.9.

13.1.4 Explicit User Agent Warnings (Avertissements Explicites de l'Agent Utilisateur)​

De nombreux agents utilisateurs permettent aux utilisateurs de passer outre les mécanismes de base de la mise en cache. Par exemple, l'agent utilisateur pourrait permettre à l'utilisateur de spécifier que les entités mises en cache (même celles explicitement périmées) ne soient jamais revalidées. Ou l'agent utilisateur pourrait ajouter habituellement "Cache-Control: max-stale=3600" à chaque requête. L'agent utilisateur ne devrait pas (SHOULD NOT) adopter par défaut un comportement non transparent, ni un comportement qui aboutit à une mise en cache anormalement inefficace, mais peut (MAY) être explicitement configuré en ce sens par une action explicite de l'utilisateur.

Si l'utilisateur a passé outre les mécanismes de base de la mise en cache, l'agent utilisateur devrait (SHOULD) indiquer explicitement à l'utilisateur chaque fois que cela aboutit à l'affichage d'informations qui pourraient ne pas satisfaire les exigences de transparence du serveur (en particulier si l'entité affichée est connue comme périmée). Comme le protocole permet normalement à l'agent utilisateur de déterminer si les réponses sont périmées ou non, cette indication ne doit être affichée que lorsque cela se produit réellement. L'indication n'a pas besoin d'être une boîte de dialogue ; elle pourrait être une icône (par exemple l'image d'un poisson en décomposition) ou un autre indicateur.

Si l'utilisateur a passé outre les mécanismes de mise en cache d'une manière qui réduit anormalement l'efficacité des caches, l'agent utilisateur devrait (SHOULD) indiquer continuellement cet état à l'utilisateur (par exemple en affichant l'image de billets en train de brûler) afin que l'utilisateur ne consomme pas par inadvertance des ressources excédentaires ni ne subisse une latence excessive.

13.1.5 Exceptions to the Rules and Warnings (Exceptions aux Règles et Avertissements)​

Dans certains cas, l'exploitant d'un cache peut (MAY) choisir de le configurer pour renvoyer des réponses périmées même lorsqu'elles ne sont pas demandées par les clients. Cette décision ne devrait pas être prise à la légère, mais peut être nécessaire pour des raisons de disponibilité ou de performance, en particulier lorsque le cache est mal connecté au serveur d'origine. Chaque fois qu'un cache renvoie une réponse périmée, il doit (MUST) la marquer comme telle (en utilisant un en-tête Warning), ce qui permet au logiciel client d'alerter l'utilisateur qu'un problème potentiel pourrait exister.

Cela permet également à l'agent utilisateur de prendre des mesures pour obtenir une réponse de première main ou fraîche. Pour cette raison, un cache ne devrait pas (SHOULD NOT) renvoyer une réponse périmée si le client en demande explicitement une de première main ou fraîche, à moins qu'il soit impossible de s'y conformer pour des raisons techniques ou de politique.

13.1.6 Client-controlled Behavior (Comportement Contrôlé par le Client)​

Bien que le serveur d'origine (et, dans une moindre mesure, les caches intermédiaires, par leur contribution à l'âge d'une réponse) soit la principale source d'informations d'expiration, dans certains cas le client peut avoir besoin de contrôler la décision d'un cache de renvoyer ou non une réponse mise en cache sans la revalider. Les clients font cela en utilisant plusieurs directives de l'en-tête Cache-Control.

La requête d'un client peut (MAY) spécifier l'âge maximal qu'il est disposé à accepter pour une réponse non revalidée ; spécifier la valeur zéro force le ou les caches à revalider toutes les réponses. Un client peut (MAY) aussi spécifier le temps minimal restant avant qu'une réponse n'expire. Ces deux options augmentent les contraintes pesant sur le comportement des caches, et ne peuvent donc pas relâcher davantage l'approximation de la transparence sémantique par le cache.

Un client peut (MAY) aussi spécifier qu'il acceptera des réponses périmées, jusqu'à un certain degré maximal de péremption. Cela assouplit les contraintes pesant sur les caches, et peut donc violer les contraintes de transparence sémantique spécifiées par le serveur d'origine, mais peut être nécessaire pour prendre en charge le fonctionnement hors connexion, ou une haute disponibilité face à une connectivité médiocre.

13.2 Expiration Model (Modèle d'Expiration)​

13.2.1 Server-Specified Expiration (Expiration Spécifiée par le Serveur)​

La mise en cache HTTP fonctionne au mieux lorsque les caches peuvent éviter entièrement d'adresser des requêtes au serveur d'origine. Le principal mécanisme permettant d'éviter les requêtes consiste, pour un serveur d'origine, à fournir un temps d'expiration explicite dans le futur, indiquant qu'une réponse peut (MAY) être utilisée pour satisfaire des requêtes ultérieures. En d'autres termes, un cache peut renvoyer une réponse fraîche sans contacter d'abord le serveur.

Nous nous attendons à ce que les serveurs attribuent aux réponses des temps d'expiration explicites dans le futur, en partant du principe que l'entité ne changera probablement pas, de manière sémantiquement significative, avant que le temps d'expiration ne soit atteint. Cela préserve normalement la transparence sémantique, tant que les temps d'expiration du serveur sont choisis avec soin.

Le mécanisme d'expiration ne s'applique qu'aux réponses prélevées dans un cache, et non aux réponses de première main transmises immédiatement au client demandeur.

Si un serveur d'origine souhaite forcer un cache sémantiquement transparent à revalider chaque requête, il peut (MAY) attribuer un temps d'expiration explicite dans le passé. Cela signifie que la réponse est toujours périmée, et donc le cache devrait (SHOULD) la revalider avant de l'utiliser pour des requêtes ultérieures. Voir la section 14.9.4 pour une manière plus restrictive de forcer la revalidation.

Si un serveur d'origine souhaite forcer n'importe quel cache HTTP/1.1, quelle que soit sa configuration, à revalider chaque requête, il devrait (SHOULD) utiliser la directive cache-control "must-revalidate" (voir la section 14.9).

Les serveurs spécifient des temps d'expiration explicites en utilisant soit l'en-tête Expires, soit la directive max-age de l'en-tête Cache-Control.

Un temps d'expiration ne peut pas être utilisé pour forcer un agent utilisateur à rafraîchir son affichage ou à recharger une ressource ; sa sémantique ne s'applique qu'aux mécanismes de mise en cache, et ces mécanismes n'ont besoin de vérifier l'état d'expiration d'une ressource que lorsqu'une nouvelle requête pour cette ressource est initiée. Voir la section 13.13 pour une explication de la différence entre les caches et les mécanismes d'historique.

13.2.2 Heuristic Expiration (Expiration Heuristique)​

Comme les serveurs d'origine ne fournissent pas toujours de temps d'expiration explicites, les caches HTTP attribuent généralement des temps d'expiration heuristiques, en employant des algorithmes qui utilisent d'autres valeurs d'en-tête (comme le temps Last-Modified) pour estimer un temps d'expiration plausible. La spécification HTTP/1.1 ne fournit pas d'algorithmes précis, mais impose des contraintes de pire cas à leurs résultats. Comme les temps d'expiration heuristiques peuvent compromettre la transparence sémantique, ils devraient être utilisés avec prudence, et nous encourageons les serveurs d'origine à fournir des temps d'expiration explicites autant que possible.

13.2.3 Age Calculations (Calculs d'Âge)​

Pour savoir si une entrée mise en cache est fraîche, un cache a besoin de savoir si son âge dépasse sa durée de fraîcheur. Nous examinons comment calculer cette dernière à la section 13.2.4 ; cette section décrit comment calculer l'âge d'une réponse ou d'une entrée de cache.

Dans cette discussion, nous utilisons le terme "now" pour signifier "la valeur courante de l'horloge sur l'hôte qui effectue le calcul". Les hôtes qui utilisent HTTP, mais surtout les hôtes exécutant des serveurs d'origine et des caches, devraient (SHOULD) utiliser NTP [28] ou un protocole similaire pour synchroniser leurs horloges sur un étalon de temps mondialement exact.

HTTP/1.1 exige des serveurs d'origine qu'ils envoient un en-tête Date, si possible, avec chaque réponse, donnant le moment où la réponse a été générée (voir la section 14.18). Nous utilisons le terme "date_value" pour désigner la valeur de l'en-tête Date, sous une forme appropriée aux opérations arithmétiques.

HTTP/1.1 utilise l'en-tête de réponse Age pour transmettre l'âge estimé du message de réponse lorsqu'il est obtenu depuis un cache. La valeur du champ Age est l'estimation par le cache de la quantité de temps écoulée depuis que la réponse a été générée ou revalidée par le serveur d'origine.

Pour l'essentiel, la valeur Age est la somme du temps pendant lequel la réponse a résidé dans chacun des caches sur le chemin depuis le serveur d'origine, plus la quantité de temps pendant laquelle elle a été en transit sur les chemins réseau.

Nous utilisons le terme "age_value" pour désigner la valeur de l'en-tête Age, sous une forme appropriée aux opérations arithmétiques.

L'âge d'une réponse peut être calculé de deux manières totalement indépendantes :

  1. now moins date_value, si l'horloge locale est raisonnablement bien synchronisée avec l'horloge du serveur d'origine. Si le résultat est négatif, il est remplacé par zéro.

2. age_value, si tous les caches sur le chemin de la réponse implémentent HTTP/1.1.

Étant donné que nous disposons de deux manières indépendantes de calculer l'âge d'une réponse lorsqu'elle est reçue, nous pouvons les combiner ainsi

       corrected_received_age = max(now - date_value, age_value)

et tant que nous avons soit des horloges presque synchronisées, soit des chemins entièrement HTTP/1.1, on obtient un résultat fiable (conservateur).

En raison des délais imposés par le réseau, un intervalle notable peut s'écouler entre le moment où un serveur génère une réponse et le moment où elle est reçue au cache ou au client sortant suivant. Si elle n'est pas corrigée, ce délai pourrait produire des âges anormalement faibles.

Comme la requête qui a produit la valeur Age renvoyée doit avoir été initiée avant la génération de cette valeur Age, nous pouvons corriger les délais imposés par le réseau en enregistrant le moment où la requête a été initiée. Ensuite, lorsqu'une valeur Age est reçue, elle doit (MUST) être interprétée par rapport au moment où la requête a été initiée, et non par rapport au moment où la réponse a été reçue. Cet algorithme produit un comportement conservateur quel que soit le délai subi. Nous calculons donc :

      corrected_initial_age = corrected_received_age
+ (now - request_time)

où "request_time" est le moment (selon l'horloge locale) où a été envoyée la requête qui a suscité cette réponse.

Résumé de l'algorithme de calcul d'âge, lorsqu'un cache reçoit une réponse :

      /*
* age_value
* is the value of Age: header received by the cache with
* this response.
* date_value
* is the value of the origin server's Date: header
* request_time
* is the (local) time when the cache made the request
* that resulted in this cached response
* response_time
* is the (local) time when the cache received the
* response
* now
* is the current (local) time
*/

apparent_age = max(0, response_time - date_value);
corrected_received_age = max(apparent_age, age_value);
response_delay = response_time - request_time;
corrected_initial_age = corrected_received_age + response_delay;
resident_time = now - response_time;
current_age = corrected_initial_age + resident_time;

Le current_age d'une entrée de cache est calculé en ajoutant au corrected_initial_age la quantité de temps (en secondes) écoulée depuis la dernière revalidation de l'entrée de cache par le serveur d'origine. Lorsqu'une réponse est générée à partir d'une entrée de cache, le cache doit (MUST) inclure dans la réponse un seul champ d'en-tête Age dont la valeur est égale au current_age de l'entrée de cache.

La présence d'un champ d'en-tête Age dans une réponse implique que la réponse n'est pas de première main. Toutefois, la réciproque n'est pas vraie, puisque l'absence d'un champ d'en-tête Age dans une réponse n'implique pas que la réponse soit de première main, à moins que tous les caches sur le chemin de la requête ne soient conformes à HTTP/1.1 (c'est-à-dire que les caches HTTP plus anciens n'implémentaient pas le champ d'en-tête Age).

13.2.4 Expiration Calculations (Calculs d'Expiration)​

Pour décider si une réponse est fraîche ou périmée, nous devons comparer sa durée de fraîcheur à son âge. L'âge est calculé comme décrit à la section 13.2.3 ; cette section décrit comment calculer la durée de fraîcheur et déterminer si une réponse a expiré. Dans la discussion ci-dessous, les valeurs peuvent être représentées sous toute forme appropriée aux opérations arithmétiques.

Nous utilisons le terme "expires_value" pour désigner la valeur de l'en-tête Expires. Nous utilisons le terme "max_age_value" pour désigner une valeur appropriée du nombre de secondes porté par la directive "max-age" de l'en-tête Cache-Control dans une réponse (voir la section 14.9.3).

La directive max-age est prioritaire sur Expires, donc si max-age est présent dans une réponse, le calcul est simplement :

      freshness_lifetime = max_age_value

Sinon, si Expires est présent dans la réponse, le calcul est :

      freshness_lifetime = expires_value - date_value

Notez qu'aucun de ces calculs n'est vulnérable à la dérive d'horloge, puisque toutes les informations proviennent du serveur d'origine.

Si ni Expires, ni Cache-Control: max-age, ni Cache-Control: s-maxage (voir la section 14.9.3) n'apparaît dans la réponse, et que la réponse n'inclut pas d'autres restrictions sur la mise en cache, le cache peut (MAY) calculer une durée de fraîcheur au moyen d'une heuristique. Le cache doit (MUST) attacher l'avertissement 113 à toute réponse dont l'âge dépasse 24 heures si un tel avertissement n'a pas déjà été ajouté.

De plus, si la réponse a bien un temps Last-Modified, la valeur d'expiration heuristique devrait (SHOULD) ne pas dépasser une certaine fraction de l'intervalle écoulé depuis ce temps. Un réglage typique de cette fraction pourrait être de 10 %.

Le calcul permettant de déterminer si une réponse a expiré est assez simple :

      response_is_fresh = (freshness_lifetime > current_age)

13.2.5 Disambiguating Expiration Values (Désambiguïsation des Valeurs d'Expiration)​

Comme les valeurs d'expiration sont attribuées de manière optimiste, il est possible que deux caches contiennent des valeurs fraîches différentes pour la même ressource.

Si un client effectuant une récupération reçoit une réponse non de première main pour une requête qui était déjà fraîche dans son propre cache, et que l'en-tête Date de son entrée de cache existante est plus récent que la Date de la nouvelle réponse, alors le client peut (MAY) ignorer la réponse. Dans ce cas, il peut (MAY) réessayer la requête avec une directive "Cache-Control: max-age=0" (voir la section 14.9), afin de forcer une vérification auprès du serveur d'origine.

Si un cache dispose de deux réponses fraîches pour la même représentation avec des validateurs différents, il doit (MUST) utiliser celle dont l'en-tête Date est le plus récent. Cette situation peut survenir parce que le cache regroupe des réponses provenant d'autres caches, ou parce qu'un client a demandé un rechargement ou une revalidation d'une entrée de cache apparemment fraîche.

13.2.6 Disambiguating Multiple Responses (Désambiguïsation de Multiples Réponses)​

Comme un client peut recevoir des réponses par des chemins multiples, de sorte que certaines réponses passent par un ensemble de caches et d'autres réponses par un ensemble différent de caches, un client peut recevoir des réponses dans un ordre différent de celui dans lequel le serveur d'origine les a envoyées. Nous souhaitons que le client utilise la réponse générée le plus récemment, même si des réponses plus anciennes sont encore apparemment fraîches.

Ni l'étiquette d'entité ni la valeur d'expiration ne peuvent imposer un ordre aux réponses, puisqu'il est possible qu'une réponse ultérieure porte intentionnellement un temps d'expiration antérieur. Les valeurs Date sont ordonnées avec une granularité d'une seconde.

Lorsqu'un client tente de revalider une entrée de cache, et que la réponse qu'il reçoit contient un en-tête Date qui semble plus ancien que celui de l'entrée existante, alors le client devrait (SHOULD) répéter la requête sans condition, et inclure

       Cache-Control: max-age=0

pour forcer tout cache intermédiaire à valider ses copies directement auprès du serveur d'origine, ou

       Cache-Control: no-cache

pour forcer tout cache intermédiaire à obtenir une nouvelle copie auprès du serveur d'origine.

Si les valeurs Date sont égales, alors le client peut (MAY) utiliser l'une ou l'autre réponse (ou peut (MAY), s'il est extrêmement prudent, demander une nouvelle réponse). Les serveurs ne doivent pas (MUST NOT) compter sur la capacité des clients à choisir de manière déterministe entre des réponses générées pendant la même seconde, si leurs temps d'expiration se chevauchent.

13.3 Validation Model (Modèle de Validation)​

Lorsqu'un cache dispose d'une entrée périmée qu'il souhaiterait utiliser comme réponse à la requête d'un client, il doit d'abord vérifier auprès du serveur d'origine (ou éventuellement d'un cache intermédiaire disposant d'une réponse fraîche) si son entrée mise en cache est encore utilisable. Nous appelons cela la "validation" de l'entrée de cache. Comme nous ne voulons pas avoir à payer le coût de la retransmission de la réponse complète si l'entrée mise en cache est bonne, et que nous ne voulons pas payer le coût d'un aller-retour supplémentaire si l'entrée mise en cache n'est pas valide, le protocole HTTP/1.1 prend en charge l'utilisation de méthodes conditionnelles.

Les principales fonctionnalités de protocole permettant de prendre en charge les méthodes conditionnelles sont celles qui concernent les "cache validator". Lorsqu'un serveur d'origine génère une réponse complète, il y attache une sorte de validateur, qui est conservé avec l'entrée de cache. Lorsqu'un client (agent utilisateur ou cache mandataire) effectue une requête conditionnelle pour une ressource dont il possède une entrée de cache, il inclut le validateur associé dans la requête.

Le serveur compare ensuite ce validateur au validateur courant de l'entité et, s'ils correspondent (voir la section 13.3.3), il répond avec un code de statut spécial (généralement 304 (Not Modified)) et sans corps d'entité. Sinon, il renvoie une réponse complète (corps d'entité compris). Ainsi, nous évitons de transmettre la réponse complète si le validateur correspond, et nous évitons un aller-retour supplémentaire s'il ne correspond pas.

Dans HTTP/1.1, une requête conditionnelle ressemble exactement à une requête normale pour la même ressource, sauf qu'elle porte un en-tête spécial (qui inclut le validateur) qui transforme implicitement la méthode (généralement GET) en requête conditionnelle.

Le protocole inclut à la fois le sens positif et le sens négatif des conditions de validation de cache. C'est-à-dire qu'il est possible de demander soit qu'une méthode soit exécutée si et seulement si un validateur correspond, soit si et seulement si aucun validateur ne correspond.

  Note: une réponse dépourvue de validateur peut néanmoins être mise en cache et servie depuis le cache jusqu'à son expiration, sauf si cela est explicitement interdit par une directive cache-control. Toutefois, un cache ne peut pas effectuer de récupération conditionnelle s'il ne dispose pas d'un validateur pour l'entité, ce qui signifie qu'il ne sera pas rafraîchissable après son expiration.

13.3.1 Last-Modified Dates (Dates de Dernière Modification)​

La valeur du champ d'en-tête d'entité Last-Modified est souvent utilisée comme validateur de cache. En termes simples, une entrée de cache est considérée comme valide si l'entité n'a pas été modifiée depuis la valeur Last-Modified.

13.3.2 Entity Tag Cache Validators (Validateurs de Cache par Étiquette d'Entité)​

La valeur du champ d'en-tête de réponse ETag, une étiquette d'entité, fournit un validateur de cache "opaque". Cela peut permettre une validation plus fiable dans les situations où il est peu commode de stocker des dates de modification, où la résolution d'une seconde des valeurs de date HTTP ne suffit pas, ou où le serveur d'origine souhaite éviter certains paradoxes pouvant résulter de l'utilisation de dates de modification.

Les étiquettes d'entité sont décrites à la section 3.11. Les en-têtes utilisés avec les étiquettes d'entité sont décrits aux sections 14.19, 14.24, 14.26 et 14.44.

13.3.3 Weak and Strong Validators (Validateurs Faibles et Forts)​

Comme les serveurs d'origine et les caches comparent tous deux deux validateurs pour décider s'ils représentent la même entité ou des entités différentes, on s'attendrait normalement à ce que, si l'entité (le corps d'entité ou n'importe quel en-tête d'entité) change de quelque manière que ce soit, le validateur associé change également. Si c'est le cas, nous appelons ce validateur un "validateur fort".

Toutefois, il peut arriver qu'un serveur préfère ne changer le validateur que lors de changements sémantiquement significatifs, et non lorsque des aspects insignifiants de l'entité changent. Un validateur qui ne change pas toujours lorsque la ressource change est un "validateur faible".

Les étiquettes d'entité sont normalement des "validateurs forts", mais le protocole prévoit un mécanisme pour marquer une étiquette d'entité comme "faible". On peut concevoir un validateur fort comme un validateur qui change chaque fois que les bits d'une entité changent, tandis qu'une valeur faible change chaque fois que la signification d'une entité change. Alternativement, on peut concevoir un validateur fort comme une partie d'un identifiant pour une entité spécifique, tandis qu'un validateur faible est une partie d'un identifiant pour un ensemble d'entités sémantiquement équivalentes.

  Note: Un exemple de validateur fort est un entier incrémenté dans un stockage stable chaque fois qu'une entité est modifiée.

Le temps de modification d'une entité, s'il est représenté avec une résolution d'une seconde, pourrait être un validateur faible, puisqu'il est possible que la ressource soit modifiée deux fois pendant une même seconde.

La prise en charge des validateurs faibles est facultative. Toutefois, les validateurs faibles permettent une mise en cache plus efficace d'objets équivalents ; par exemple, un compteur de visites sur un site est probablement suffisant s'il est mis à jour tous les quelques jours ou semaines, et toute valeur pendant cette période est probablement "suffisamment bonne" pour être équivalente.

Un "usage" d'un validateur a lieu soit lorsqu'un client génère une requête et inclut le validateur dans un champ d'en-tête de validation, soit lorsqu'un serveur compare deux validateurs.

Les validateurs forts sont utilisables dans n'importe quel contexte. Les validateurs faibles ne sont utilisables que dans des contextes qui ne dépendent pas de l'égalité exacte d'une entité. Par exemple, l'un ou l'autre type est utilisable pour un GET conditionnel d'une entité complète. Toutefois, seul un validateur fort est utilisable pour une récupération de sous-intervalle, car sinon le client pourrait se retrouver avec une entité interne incohérente.

Les clients peuvent (MAY) émettre des requêtes GET simples (non de sous-intervalle) avec des validateurs faibles ou avec des validateurs forts. Les clients ne doivent pas (MUST NOT) utiliser de validateurs faibles dans d'autres formes de requête.

La seule fonction que le protocole HTTP/1.1 définit sur les validateurs est la comparaison. Il existe deux fonctions de comparaison de validateurs, selon que le contexte de comparaison autorise ou non l'usage de validateurs faibles :

  - La fonction de comparaison forte : pour être considérés comme égaux, les deux validateurs doivent (MUST) être identiques en tous points, et ni l'un ni l'autre ne doit (MUST NOT) être faible.

- La fonction de comparaison faible : pour être considérés comme égaux, les deux validateurs doivent (MUST) être identiques en tous points, mais l'un ou l'autre, ou les deux, peuvent (MAY) être marqués comme "faibles" sans que cela affecte le résultat.

Une étiquette d'entité est forte, sauf si elle est explicitement marquée comme faible. La section 3.11 donne la syntaxe des étiquettes d'entité.

Un temps Last-Modified, lorsqu'il est utilisé comme validateur dans une requête, est implicitement faible, sauf s'il est possible de déduire qu'il est fort, à l'aide des règles suivantes :

  - Le validateur est comparé par un serveur d'origine au validateur courant réel de l'entité, et

- ce serveur d'origine sait de manière fiable que l'entité associée n'a pas changé deux fois pendant la seconde couverte par le validateur présenté.

ou

  - Le validateur est sur le point d'être utilisé par un client dans un en-tête If-Modified-Since ou If-Unmodified-Since, parce que le client possède une entrée de cache pour l'entité associée, et

- cette entrée de cache comprend une valeur Date, qui donne le moment où le serveur d'origine a envoyé la réponse originale, et

- le temps Last-Modified présenté est antérieur d'au moins 60 secondes à la valeur Date.

ou

  - Le validateur est comparé par un cache intermédiaire au validateur stocké dans son entrée de cache pour l'entité, et

- cette entrée de cache comprend une valeur Date, qui donne le moment où le serveur d'origine a envoyé la réponse originale, et

- le temps Last-Modified présenté est antérieur d'au moins 60 secondes à la valeur Date.

Cette méthode repose sur le fait que, si deux réponses différentes ont été envoyées par le serveur d'origine pendant la même seconde, mais que toutes deux avaient le même temps Last-Modified, alors au moins l'une de ces réponses aurait une valeur Date égale à son temps Last-Modified. La limite arbitraire de 60 secondes prémunit contre la possibilité que les valeurs Date et Last-Modified soient générées à partir d'horloges différentes, ou à des moments quelque peu différents pendant la préparation de la réponse. Une implémentation peut (MAY) utiliser une valeur supérieure à 60 secondes, si elle estime que 60 secondes sont trop courtes.

Si un client souhaite effectuer une récupération de sous-intervalle sur une valeur pour laquelle il ne dispose que d'un temps Last-Modified et d'aucun validateur opaque, il peut (MAY) le faire uniquement si le temps Last-Modified est fort au sens décrit ici.

Un cache ou un serveur d'origine recevant une requête conditionnelle autre qu'une requête GET à corps complet doit (MUST) utiliser la fonction de comparaison forte pour évaluer la condition.

Ces règles permettent aux caches et aux clients HTTP/1.1 d'effectuer en toute sécurité des récupérations de sous-intervalle sur des valeurs obtenues auprès de serveurs HTTP/1.0.

13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates (Règles pour Quand Utiliser les Étiquettes d'Entité et les Dates de Dernière Modification)​

Nous adoptons un ensemble de règles et de recommandations à l'intention des serveurs d'origine, des clients et des caches, concernant le moment où les divers types de validateurs devraient être utilisés, et dans quels buts.

Serveurs d'origine HTTP/1.1 :

  - DEVRAIENT (SHOULD) envoyer un validateur d'étiquette d'entité, à moins qu'il ne soit pas possible d'en générer un.

- PEUVENT (MAY) envoyer une étiquette d'entité faible au lieu d'une étiquette d'entité forte, si des considérations de performance soutiennent l'usage d'étiquettes d'entité faibles, ou s'il n'est pas possible d'envoyer une étiquette d'entité forte.

- DEVRAIENT (SHOULD) envoyer une valeur Last-Modified s'il est possible d'en envoyer une, à moins que le risque d'une rupture de la transparence sémantique pouvant résulter de l'utilisation de cette date dans un en-tête If-Modified-Since ne conduise à de graves problèmes.

En d'autres termes, le comportement préféré pour un serveur d'origine HTTP/1.1 est d'envoyer à la fois une étiquette d'entité forte et une valeur Last-Modified.

Pour être légal, une étiquette d'entité forte doit (MUST) changer chaque fois que la valeur de l'entité associée change de quelque manière que ce soit. Une étiquette d'entité faible devrait (SHOULD) changer chaque fois que l'entité associée change de manière sémantiquement significative.

  Note: afin de fournir une mise en cache sémantiquement transparente, un serveur d'origine doit éviter de réutiliser une valeur d'étiquette d'entité forte spécifique pour deux entités différentes, ou de réutiliser une valeur d'étiquette d'entité faible spécifique pour deux entités sémantiquement différentes. Les entrées de cache peuvent persister pendant des durées arbitrairement longues, indépendamment des temps d'expiration, il pourrait donc être inapproprié de s'attendre à ce qu'un cache ne tente plus jamais de valider une entrée à l'aide d'un validateur qu'il a obtenu à un moment donné dans le passé.

Clients HTTP/1.1 :

  - Si une étiquette d'entité a été fournie par le serveur d'origine, ils DOIVENT (MUST) utiliser cette étiquette d'entité dans toute requête conditionnelle de cache (en utilisant If-Match ou If-None-Match).

- Si seule une valeur Last-Modified a été fournie par le serveur d'origine, ils DEVRAIENT (SHOULD) utiliser cette valeur dans les requêtes conditionnelles de cache hors sous-intervalle (en utilisant If-Modified-Since).

- Si seule une valeur Last-Modified a été fournie par un serveur d'origine HTTP/1.0, ils PEUVENT (MAY) utiliser cette valeur dans les requêtes conditionnelles de cache de sous-intervalle (en utilisant If-Unmodified-Since). L'agent utilisateur DEVRAIT (SHOULD) offrir un moyen de désactiver cela, en cas de difficulté.

- Si une étiquette d'entité et une valeur Last-Modified ont toutes deux été fournies par le serveur d'origine, ils DEVRAIENT (SHOULD) utiliser les deux validateurs dans les requêtes conditionnelles de cache. Cela permet aux caches HTTP/1.0 comme HTTP/1.1 de répondre de manière appropriée.

Un serveur d'origine HTTP/1.1, à la réception d'une requête conditionnelle qui inclut à la fois une date Last-Modified (par exemple dans un champ d'en-tête If-Modified-Since ou If-Unmodified-Since) et une ou plusieurs étiquettes d'entité (par exemple dans un champ d'en-tête If-Match, If-None-Match ou If-Range) comme validateurs de cache, ne doit pas (MUST NOT) renvoyer un statut de réponse 304 (Not Modified) à moins que cela ne soit cohérent avec tous les champs d'en-tête conditionnels de la requête.

Un cache mandataire HTTP/1.1, à la réception d'une requête conditionnelle qui inclut à la fois une date Last-Modified et une ou plusieurs étiquettes d'entité comme validateurs de cache, ne doit pas (MUST NOT) renvoyer au client une réponse mise en cache localement à moins que cette réponse mise en cache ne soit cohérente avec tous les champs d'en-tête conditionnels de la requête.

  Note: Le principe général sous-jacent à ces règles est que les serveurs et les clients HTTP/1.1 devraient transmettre autant d'informations non redondantes qu'il en est disponible dans leurs réponses et requêtes. Les systèmes HTTP/1.1 qui reçoivent ces informations feront les hypothèses les plus conservatrices sur les validateurs qu'ils reçoivent.

Les clients et les caches HTTP/1.0 ignoreront les étiquettes d'entité. En général, les valeurs last-modified reçues ou utilisées par ces systèmes prendront en charge une mise en cache transparente et efficace, et donc les serveurs d'origine HTTP/1.1 devraient fournir des valeurs Last-Modified. Dans les rares cas où l'utilisation d'une valeur Last-Modified comme validateur par un système HTTP/1.0 pourrait entraîner un problème grave, les serveurs d'origine HTTP/1.1 ne devraient pas en fournir.

13.3.5 Non-validating Conditionals (Conditionnels Non Validants)​

Le principe sous-jacent aux étiquettes d'entité est que seul l'auteur du service connaît suffisamment la sémantique d'une ressource pour choisir un mécanisme approprié de validation de cache, et que la spécification de toute fonction de comparaison de validateurs plus complexe que l'égalité d'octets ouvrirait une boîte de Pandore. Ainsi, les comparaisons de tout autre en-tête (sauf Last-Modified, pour la compatibilité avec HTTP/1.0) ne sont jamais utilisées aux fins de validation d'une entrée de cache.

13.4 Response Cacheability (Cachabilité de la Réponse)​

Sauf contrainte spécifique par une directive cache-control (section 14.9), un système de mise en cache peut (MAY) toujours stocker une réponse réussie (voir la section 13.8) comme entrée de cache, peut (MAY) la renvoyer sans validation si elle est fraîche, et peut (MAY) la renvoyer après une validation réussie. Si aucune étiquette de validation de cache ni aucun temps d'expiration explicite n'est associé à une réponse, nous ne nous attendons pas à ce qu'elle soit mise en cache, mais certains caches peuvent (MAY) violer cette attente (par exemple lorsque la connectivité réseau est faible ou nulle). Un client peut généralement détecter qu'une telle réponse a été prélevée dans un cache en comparant l'en-tête Date à l'heure courante.

  Note: certains caches HTTP/1.0 sont connus pour violer cette attente sans fournir aucun avertissement.

Toutefois, dans certains cas, il peut être inapproprié qu'un cache conserve une entité, ou la renvoie en réponse à une requête ultérieure. Cela peut tenir au fait que l'auteur du service juge nécessaire une transparence sémantique absolue, ou à des considérations de sécurité ou de vie privée. Certaines directives cache-control sont donc prévues afin que le serveur puisse indiquer que certaines entités de ressource, ou parties de celles-ci, ne doivent pas être mises en cache, indépendamment d'autres considérations.

Notez que la section 14.8 empêche normalement un cache partagé d'enregistrer et de renvoyer une réponse à une requête précédente si cette requête incluait un en-tête Authorization.

Une réponse reçue avec un code de statut 200, 203, 206, 300, 301 ou 410 peut (MAY) être stockée par un cache et utilisée en réponse à une requête ultérieure, sous réserve du mécanisme d'expiration, à moins qu'une directive cache-control n'interdise la mise en cache. Toutefois, un cache qui ne prend pas en charge les en-têtes Range et Content-Range ne doit pas (MUST NOT) mettre en cache les réponses 206 (Partial Content).

Une réponse reçue avec tout autre code de statut (par exemple les codes de statut 302 et 307) ne doit pas (MUST NOT) être renvoyée en réponse à une requête ultérieure, à moins qu'il n'existe des directives cache-control ou un ou plusieurs autres en-têtes qui l'autorisent explicitement. Par exemple, ceux-ci comprennent : un en-tête Expires (section 14.21) ; une directive cache-control "max-age", "s-maxage", "must-revalidate", "proxy-revalidate", "public" ou "private" (section 14.9).

13.5 Constructing Responses From Caches (Construction de Réponses à partir des Caches)​

Le but d'un cache HTTP est de stocker les informations reçues en réponse à des requêtes, afin de les utiliser pour répondre à de futures requêtes. Dans de nombreux cas, un cache renvoie simplement les parties appropriées d'une réponse au demandeur. Toutefois, si le cache détient une entrée de cache fondée sur une réponse précédente, il peut devoir combiner des parties d'une nouvelle réponse avec ce qui est détenu dans l'entrée de cache.

13.5.1 End-to-end and Hop-by-hop Headers (En-têtes de Bout en Bout et Saut par Saut)​

Aux fins de la définition du comportement des caches et des mandataires sans mise en cache, nous divisons les en-têtes HTTP en deux catégories :

  - Les en-têtes de bout en bout, qui sont transmis au destinataire final d'une requête ou d'une réponse. Les en-têtes de bout en bout des réponses DOIVENT (MUST) être stockés comme partie d'une entrée de cache et DOIVENT (MUST) être transmis dans toute réponse formée à partir d'une entrée de cache.

- Les en-têtes saut par saut, qui n'ont de sens que pour une seule connexion au niveau du transport, et ne sont ni stockés par les caches ni transmis par les mandataires.

Les en-têtes HTTP/1.1 suivants sont des en-têtes saut par saut :

  - Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailers
- Transfer-Encoding
- Upgrade

Tous les autres en-têtes définis par HTTP/1.1 sont des en-têtes de bout en bout.

Les autres en-têtes saut par saut DOIVENT (MUST) être énumérés dans un en-tête Connection (section 14.10) pour être introduits dans HTTP/1.1 (ou une version ultérieure).

13.5.2 Non-modifiable Headers (En-têtes Non Modifiables)​

Certaines fonctionnalités du protocole HTTP/1.1, comme la Digest Authentication, dépendent de la valeur de certains en-têtes de bout en bout. Un mandataire transparent ne devrait pas (SHOULD NOT) modifier un en-tête de bout en bout, à moins que la définition de cet en-tête ne l'exige ou ne l'autorise spécifiquement.

Un mandataire transparent ne doit pas (MUST NOT) modifier aucun des champs suivants dans une requête ou une réponse, et il ne doit pas (MUST NOT) ajouter aucun de ces champs s'ils ne sont pas déjà présents :

  - Content-Location

- Content-MD5

- ETag

- Last-Modified

Un mandataire transparent ne doit pas (MUST NOT) modifier aucun des champs suivants dans une réponse :

  - Expires

mais il peut (MAY) ajouter l'un de ces champs s'il n'est pas déjà présent. Si un en-tête Expires est ajouté, il doit (MUST) lui être donné un field-value identique à celui de l'en-tête Date de cette réponse.

Un mandataire ne doit pas (MUST NOT) modifier ni ajouter aucun des champs suivants dans un message qui contient la directive cache-control no-transform, ni dans aucune requête :

  - Content-Encoding

- Content-Range

- Content-Type

Un mandataire non transparent peut (MAY) modifier ou ajouter ces champs à un message qui n'inclut pas no-transform, mais s'il le fait, il doit (MUST) ajouter un avertissement 214 (Transformation applied) si aucun n'apparaît déjà dans le message (voir la section 14.46).

      Warning: unnecessary modification of end-to-end headers might
cause authentication failures if stronger authentication
mechanisms are introduced in later versions of HTTP. Such
authentication mechanisms MAY rely on the values of header fields
not listed here.

Le champ Content-Length d'une requête ou d'une réponse est ajouté ou supprimé selon les règles de la section 4.4. Un mandataire transparent doit (MUST) préserver l'entity-length (section 7.2.2) du corps d'entité, bien qu'il puisse (MAY) modifier la transfer-length (section 4.4).

13.5.3 Combining Headers (Combinaison d'En-têtes)​

Lorsqu'un cache effectue une requête de validation auprès d'un serveur, et que le serveur fournit une réponse 304 (Not Modified) ou une réponse 206 (Partial Content), le cache construit ensuite une réponse à envoyer au client demandeur.

Si le code de statut est 304 (Not Modified), le cache utilise le corps d'entité stocké dans l'entrée de cache comme corps d'entité de cette réponse sortante. Si le code de statut est 206 (Partial Content) et que les en-têtes ETag ou Last-Modified correspondent exactement, le cache peut (MAY) combiner le contenu stocké dans l'entrée de cache avec le nouveau contenu reçu dans la réponse et utiliser le résultat comme corps d'entité de cette réponse sortante (voir 13.5.4).

Les en-têtes de bout en bout stockés dans l'entrée de cache sont utilisés pour la réponse construite, à ceci près que

  - tout en-tête Warning stocké avec un warn-code 1xx (voir la section 14.46) doit (MUST) être supprimé de l'entrée de cache et de la réponse transmise.

- tout en-tête Warning stocké avec un warn-code 2xx doit (MUST) être conservé dans l'entrée de cache et dans la réponse transmise.

- tout en-tête de bout en bout fourni dans la réponse 304 ou 206 doit (MUST) remplacer les en-têtes correspondants de l'entrée de cache.

À moins que le cache ne décide de supprimer l'entrée de cache, il doit (MUST) également remplacer les en-têtes de bout en bout stockés avec l'entrée de cache par les en-têtes correspondants reçus dans la réponse entrante, à l'exception des en-têtes Warning comme décrit juste ci-dessus. Si un header field-name de la réponse entrante correspond à plus d'un en-tête de l'entrée de cache, tous ces anciens en-têtes DOIVENT (MUST) être remplacés.

En d'autres termes, l'ensemble des en-têtes de bout en bout reçus dans la réponse entrante supplante tous les en-têtes de bout en bout correspondants stockés avec l'entrée de cache (à l'exception des en-têtes Warning stockés avec un warn-code 1xx, qui sont supprimés même s'ils ne sont pas supplantés).

  Note: cette règle permet à un serveur d'origine d'utiliser une réponse 304 (Not Modified) ou 206 (Partial Content) pour mettre à jour tout en-tête associé à une réponse précédente pour la même entité ou ses sous-intervalles, bien que cela ne soit pas toujours pertinent ou correct. Cette règle ne permet pas à un serveur d'origine d'utiliser une réponse 304 (Not Modified) ou 206 (Partial Content) pour supprimer entièrement un en-tête qu'il avait fourni avec une réponse précédente.

13.5.4 Combining Byte Ranges (Combinaison de Plages d'Octets)​

Une réponse peut ne transférer qu'un sous-intervalle des octets d'un corps d'entité, soit parce que la requête incluait une ou plusieurs spécifications Range, soit parce qu'une connexion a été interrompue prématurément. Après plusieurs transferts de ce type, un cache peut avoir reçu plusieurs plages du même corps d'entité.

Si un cache dispose d'un ensemble stocké non vide de sous-intervalles pour une entité, et qu'une réponse entrante transfère un autre sous-intervalle, le cache peut (MAY) combiner le nouveau sous-intervalle avec l'ensemble existant si les deux conditions suivantes sont réunies :

  - La réponse entrante et l'entrée de cache ont toutes deux un validateur de cache.

- Les deux validateurs de cache correspondent en utilisant la fonction de comparaison forte (voir la section 13.3.3).

Si l'une ou l'autre des exigences n'est pas satisfaite, le cache doit (MUST) utiliser uniquement la réponse partielle la plus récente (d'après les valeurs Date transmises avec chaque réponse, et en utilisant la réponse entrante si ces valeurs sont égales ou absentes), et doit (MUST) écarter les autres informations partielles.

13.6 Caching Negotiated Responses (Mise en Cache des Réponses Négociées)​

L'utilisation de la négociation de contenu pilotée par le serveur (section 12.1), indiquée par la présence d'un champ d'en-tête Vary dans une réponse, modifie les conditions et la procédure selon lesquelles un cache peut utiliser la réponse pour des requêtes ultérieures. Voir la section 14.44 pour l'utilisation du champ d'en-tête Vary par les serveurs.

Un serveur devrait (SHOULD) utiliser le champ d'en-tête Vary pour informer un cache des champs d'en-tête de requête qui ont été utilisés pour choisir parmi plusieurs représentations d'une réponse cachable soumise à une négociation pilotée par le serveur. L'ensemble des champs d'en-tête nommés par la valeur du champ Vary est connu sous le nom de request-header "selecting".

Lorsque le cache reçoit une requête ultérieure dont le Request-URI spécifie une ou plusieurs entrées de cache comprenant un champ d'en-tête Vary, le cache ne doit pas (MUST NOT) utiliser une telle entrée de cache pour construire une réponse à la nouvelle requête, à moins que tous les request-header selecting présents dans la nouvelle requête ne correspondent aux request-header stockés correspondants de la requête originale.

Les request-header selecting de deux requêtes sont définis comme correspondants si et seulement si les request-header selecting de la première requête peuvent être transformés en les request-header selecting de la seconde requête en ajoutant ou en supprimant des espaces linéaires (LWS) aux endroits où cela est autorisé par le BNF correspondant, et/ou en combinant plusieurs champs message-header ayant le même field name selon les règles relatives aux message header de la section 4.2.

Une valeur de champ Vary égale à "*" ne correspond jamais, et les requêtes ultérieures sur cette ressource ne peuvent être correctement interprétées que par le serveur d'origine.

Si les champs d'en-tête de requête selecting de l'entrée mise en cache ne correspondent pas aux champs d'en-tête de requête selecting de la nouvelle requête, alors le cache ne doit pas (MUST NOT) utiliser une entrée mise en cache pour satisfaire la requête, à moins qu'il ne relaie d'abord la nouvelle requête au serveur d'origine sous forme de requête conditionnelle et que le serveur ne réponde par 304 (Not Modified), en incluant une étiquette d'entité ou un Content-Location qui indique l'entité à utiliser.

Si une étiquette d'entité a été attribuée à une représentation mise en cache, la requête transmise devrait (SHOULD) être conditionnelle et inclure les étiquettes d'entité dans un champ d'en-tête If-None-Match provenant de toutes ses entrées de cache pour la ressource. Cela communique au serveur l'ensemble des entités actuellement détenues par le cache, de sorte que, si l'une de ces entités correspond à l'entité demandée, le serveur puisse utiliser le champ d'en-tête ETag de sa réponse 304 (Not Modified) pour indiquer au cache quelle entrée est appropriée. Si l'entity-tag de la nouvelle réponse correspond à celui d'une entrée existante, la nouvelle réponse devrait (SHOULD) être utilisée pour mettre à jour les champs d'en-tête de l'entrée existante, et le résultat doit (MUST) être renvoyé au client.

Si l'une des entrées de cache existantes ne contient qu'un contenu partiel pour l'entité associée, son entity-tag ne devrait pas (SHOULD NOT) être inclus dans le champ d'en-tête If-None-Match, à moins que la requête ne porte sur une plage qui serait entièrement satisfaite par cette entrée.

Si un cache reçoit une réponse réussie dont le champ Content-Location correspond à celui d'une entrée de cache existante pour le même Request-URI, dont l'entity-tag diffère de celui de l'entrée existante, et dont la Date est plus récente que celle de l'entrée existante, l'entrée existante ne devrait pas (SHOULD NOT) être renvoyée en réponse à de futures requêtes et devrait (SHOULD) être supprimée du cache.

13.7 Shared and Non-Shared Caches (Caches Partagés et Non Partagés)​

Pour des raisons de sécurité et de vie privée, il est nécessaire d'établir une distinction entre les caches "partagés" et "non partagés". Un cache non partagé est un cache accessible à un seul utilisateur. L'accessibilité dans ce cas devrait (SHOULD) être assurée par des mécanismes de sécurité appropriés. Tous les autres caches sont considérés comme "partagés". D'autres sections de cette spécification imposent certaines contraintes au fonctionnement des caches partagés afin de prévenir la perte de vie privée ou la défaillance des contrôles d'accès.

13.8 Errors or Incomplete Response Cache Behavior (Comportement de Cache pour Erreurs ou Réponses Incomplètes)​

Un cache qui reçoit une réponse incomplète (par exemple avec moins d'octets de données que ce qui est spécifié dans un en-tête Content-Length) peut (MAY) stocker la réponse. Toutefois, le cache doit (MUST) la traiter comme une réponse partielle. Les réponses partielles peuvent (MAY) être combinées comme décrit à la section 13.5.4 ; le résultat peut être une réponse complète ou peut rester partiel. Un cache ne doit pas (MUST NOT) renvoyer une réponse partielle à un client sans la marquer explicitement comme telle, en utilisant le code de statut 206 (Partial Content). Un cache ne doit pas (MUST NOT) renvoyer une réponse partielle en utilisant un code de statut 200 (OK).

Si un cache reçoit une réponse 5xx alors qu'il tente de revalider une entrée, il peut (MAY) soit transmettre cette réponse au client demandeur, soit agir comme si le serveur n'avait pas répondu. Dans ce dernier cas, il peut (MAY) renvoyer une réponse reçue précédemment, à moins que l'entrée mise en cache n'inclue la directive cache-control "must-revalidate" (voir la section 14.9).

13.9 Side Effects of GET and HEAD (Effets Secondaires de GET et HEAD)​

À moins que le serveur d'origine n'interdise explicitement la mise en cache de leurs réponses, l'application des méthodes GET et HEAD à n'importe quelle ressource ne devrait pas (SHOULD NOT) avoir d'effets secondaires qui conduiraient à un comportement erroné si ces réponses étaient prélevées dans un cache. Elles peuvent (MAY) néanmoins avoir des effets secondaires, mais un cache n'est pas tenu de prendre en compte de tels effets secondaires dans ses décisions de mise en cache. On attend toujours des caches qu'ils respectent les restrictions explicites d'un serveur d'origine en matière de mise en cache.

Nous notons une exception à cette règle : comme certaines applications ont traditionnellement utilisé des GET et des HEAD avec des URL de requête (celles contenant un "?" dans la partie rel_path) pour effectuer des opérations ayant des effets secondaires significatifs, les caches ne doivent pas (MUST NOT) traiter comme fraîches les réponses à de tels URI, à moins que le serveur ne fournisse un temps d'expiration explicite. Cela signifie spécifiquement que les réponses provenant de serveurs HTTP/1.0 pour de tels URI ne devraient pas (SHOULD NOT) être prélevées dans un cache. Voir la section 9.1.1 pour des informations connexes.

13.10 Invalidation After Updates or Deletions (Invalidation Après Mises à Jour ou Suppressions)​

L'effet de certaines méthodes exécutées sur une ressource au niveau du serveur d'origine peut rendre une ou plusieurs entrées de cache existantes non transparentes et invalides. C'est-à-dire que, bien qu'elles puissent continuer d'être "fraîches", elles ne reflètent pas fidèlement ce que le serveur d'origine renverrait pour une nouvelle requête sur cette ressource.

Le protocole HTTP n'a aucun moyen de garantir que toutes ces entrées de cache soient marquées comme invalides. Par exemple, la requête qui a provoqué le changement au niveau du serveur d'origine peut ne pas être passée par le mandataire où une entrée de cache est stockée. Toutefois, plusieurs règles aident à réduire la probabilité d'un comportement erroné.

Dans cette section, l'expression "invalider une entité" signifie que le cache supprimera toutes les instances de cette entité de son stockage, ou les marquera comme "invalides" et nécessitant une revalidation obligatoire avant de pouvoir être renvoyées en réponse à une requête ultérieure.

Certaines méthodes HTTP DOIVENT (MUST) amener un cache à invalider une entité. Il s'agit soit de l'entité à laquelle fait référence le Request-URI, soit de celles auxquelles font référence les en-têtes Location ou Content-Location (s'ils sont présents). Ces méthodes sont :

  - PUT

- DELETE

- POST

Afin de prévenir les attaques par déni de service, une invalidation fondée sur l'URI d'un en-tête Location ou Content-Location ne doit (MUST) être effectuée que si la partie host est la même que dans le Request-URI.

Un cache qui laisse passer des requêtes pour des méthodes qu'il ne comprend pas devrait (SHOULD) invalider toutes les entités auxquelles fait référence le Request-URI.

13.11 Write-Through Mandatory (Écriture Traversante Obligatoire)​

Toutes les méthodes dont on peut s'attendre à ce qu'elles provoquent des modifications des ressources du serveur d'origine DOIVENT (MUST) être écrites de bout en bout vers le serveur d'origine (write-through). Cela inclut actuellement toutes les méthodes sauf GET et HEAD. Un cache ne doit pas (MUST NOT) répondre à une telle requête d'un client avant d'avoir transmis la requête au serveur entrant, et d'avoir reçu une réponse correspondante du serveur entrant. Cela n'empêche pas un cache mandataire d'envoyer une réponse 100 (Continue) avant que le serveur entrant n'ait envoyé sa réponse finale.

L'alternative (connue sous le nom de mise en cache "write-back" ou "copy-back") n'est pas autorisée dans HTTP/1.1, en raison de la difficulté à fournir des mises à jour cohérentes et des problèmes découlant d'une défaillance du serveur, du cache ou du réseau avant l'écriture différée.

13.12 Cache Replacement (Remplacement de Cache)​

Si une nouvelle réponse cachable (voir les sections 14.9.2, 13.2.5, 13.2.6 et 13.8) est reçue d'une ressource alors que des réponses existantes pour la même ressource sont mises en cache, le cache devrait (SHOULD) utiliser la nouvelle réponse pour répondre à la requête courante. Il peut (MAY) l'insérer dans le stockage du cache et peut (MAY), si elle satisfait à toutes les autres exigences, l'utiliser pour répondre à toute requête future qui aurait auparavant provoqué le renvoi de l'ancienne réponse. S'il insère la nouvelle réponse dans le stockage du cache, les règles de la section 13.5.3 s'appliquent.

  Note: une nouvelle réponse dont la valeur d'en-tête Date est plus ancienne que celle des réponses mises en cache existantes n'est pas cachable.

13.13 History Lists (Listes d'Historique)​

Les agents utilisateurs ont souvent des mécanismes d'historique, tels que des boutons "Retour" et des listes d'historique, qui peuvent servir à réafficher une entité récupérée plus tôt dans une session.

Les mécanismes d'historique et les caches sont différents. En particulier, les mécanismes d'historique ne devraient pas (SHOULD NOT) chercher à montrer une vue sémantiquement transparente de l'état courant d'une ressource. Au contraire, un mécanisme d'historique est destiné à montrer exactement ce que l'utilisateur a vu au moment où la ressource a été récupérée.

Par défaut, un temps d'expiration ne s'applique pas aux mécanismes d'historique. Si l'entité est encore dans le stockage, un mécanisme d'historique devrait (SHOULD) l'afficher même si l'entité a expiré, à moins que l'utilisateur n'ait spécifiquement configuré l'agent pour rafraîchir les documents d'historique expirés.

Cela ne doit pas être interprété comme interdisant au mécanisme d'historique d'indiquer à l'utilisateur qu'une vue pourrait être périmée.

  Note: si les mécanismes de liste d'historique empêchent inutilement les utilisateurs de consulter des ressources périmées, cela tendra à forcer les auteurs de services à éviter d'utiliser les contrôles d'expiration et de cache de HTTP alors qu'ils souhaiteraient par ailleurs le faire. Les auteurs de services peuvent juger important que les utilisateurs ne reçoivent pas de messages d'erreur ou d'avertissement lorsqu'ils utilisent des contrôles de navigation (tels que BACK) pour consulter des ressources récupérées précédemment. Même si de telles ressources ne devraient parfois pas être mises en cache, ou devraient expirer rapidement, des considérations d'interface utilisateur peuvent forcer les auteurs de services à recourir à d'autres moyens d'empêcher la mise en cache (par exemple des URL "once-only") afin de ne pas subir les effets de mécanismes d'historique fonctionnant mal.