Aller au contenu principal

8. Données et Métadonnées de Représentation (Representation Data and Metadata)

8.1. Données de Représentation (Representation Data)

Les données de représentation associées à un message HTTP sont soit fournies en tant que contenu du message, soit référencées par la sémantique du message et l'URI cible. Les données de représentation sont dans un format et un encodage définis par les champs d'en-tête de métadonnées de représentation.

Le type de données des données de représentation est déterminé via les champs d'en-tête Content-Type et Content-Encoding. Ceux-ci définissent un modèle d'encodage à deux couches et ordonné :

representation-data := Content-Encoding( Content-Type( data ) )

8.2. Métadonnées de Représentation (Representation Metadata)

Les champs d'en-tête de représentation fournissent des métadonnées sur la représentation. Lorsqu'un message inclut du contenu, les champs d'en-tête de représentation décrivent comment interpréter ces données. Dans une réponse à une requête HEAD, les champs d'en-tête de représentation décrivent les données de représentation qui auraient été incluses dans le contenu si la même requête avait été un GET.

8.3. Content-Type

Le champ d'en-tête「Content-Type」indique le type de média de la représentation associée : soit la représentation incluse dans le contenu du message, soit la représentation sélectionnée, telle que déterminée par la sémantique du message. Le type de média indiqué définit à la fois le format des données et la manière dont ces données sont destinées à être traitées par un destinataire, dans le cadre de la sémantique du message reçu, après le décodage de tout codage de contenu indiqué par Content-Encoding.

Content-Type = media-type

Les types de média sont définis dans la Section 8.3.1. Un exemple du champ est

Content-Type: text/html; charset=ISO-8859-4

Un expéditeur qui génère un message contenant du contenu DEVRAIT (SHOULD) générer un champ d'en-tête Content-Type dans ce message à moins que l'expéditeur ne connaisse pas le type de média prévu de la représentation incluse. Si un champ d'en-tête Content-Type n'est pas présent, le destinataire PEUT (MAY) soit supposer un type de média de「application/octet-stream」([RFC2046], Section 4.5.1), soit examiner les données pour déterminer leur type.

En pratique, les propriétaires de ressources ne configurent pas toujours correctement leur serveur d'origine pour fournir le bon Content-Type pour une représentation donnée. Certains agents utilisateurs examinent le contenu et, dans certains cas, remplacent le type reçu (par exemple, voir [Sniffing]). Ce「reniflage MIME」risque de tirer des conclusions incorrectes sur les données, ce qui pourrait exposer l'utilisateur à des risques de sécurité supplémentaires (par exemple,「élévation de privilèges」). De plus, il arrive souvent que différents types de médias utilisent le même format de données mais diffèrent uniquement dans le traitement prévu de ces données, ce qui ne peut pas être distingué en inspectant les données seules. Lorsque le reniflage est mis en œuvre, les implémenteurs sont encouragés à fournir un moyen pour l'utilisateur de le désactiver.

Bien que Content-Type soit défini comme un champ singleton, il est parfois généré incorrectement plusieurs fois, ce qui donne une valeur de champ combinée qui ressemble à une liste. Les destinataires tentent souvent de gérer cette erreur en utilisant le dernier membre syntaxiquement valide de la liste, ce qui peut entraîner des problèmes potentiels d'interopérabilité et de sécurité si différentes implémentations ont des comportements de gestion des erreurs différents.

8.3.1. Type de Média (Media Type)

HTTP utilise des types de média [RFC2046] dans les champs d'en-tête Content-Type (Section 8.3) et Accept (Section 12.5.1) afin de fournir un typage de données et une négociation de type ouverts et extensibles. Les types de média définissent à la fois un format de données et divers modèles de traitement : comment traiter ces données conformément au contexte du message.

media-type = type "/" subtype parameters
type = token
subtype = token

Le type/sous-type PEUT (MAY) être suivi de paramètres délimités par des points-virgules (Section 5.6.6) sous la forme de paires nom/valeur. La présence ou l'absence d'un paramètre peut être significative pour le traitement d'un type de média, selon sa définition dans le registre des types de média.

Une valeur de paramètre qui correspond à la production token peut être transmise sans guillemets. Cependant, une valeur de paramètre avec un caractère invalide (c'est-à-dire qui ne correspond pas à la production token) DOIT (MUST) être entre guillemets doubles (Section 5.6.4) lors de l'envoi.

parameter      = parameter-name "=" parameter-value
parameter-name = token
parameter-value = ( token / quoted-string )

Note : Certains destinataires de paramètres de type de média les traitent de manière sensible à la casse. Il est généralement recommandé d'utiliser des minuscules pour les noms de paramètres et d'utiliser la casse la plus courante pour les valeurs de paramètres.

Les types de média devraient être enregistrés auprès de l'IANA selon les procédures définies dans [BCP13].

Note : Contrairement à certaines constructions similaires dans d'autres champs d'en-tête, les paramètres de type de média ne permettent pas d'espace blanc (même「mauvais」) autour du caractère「=」.

8.3.2. Charset

HTTP utilise des noms de jeux de caractères dans les champs d'en-tête Content-Type (Section 8.3) et Accept-Charset (déprécié ; Section 12.5.2) pour indiquer ou négocier le schéma d'encodage de caractères d'une représentation textuelle. Un jeu de caractères est identifié par un jeton insensible à la casse.

charset = token

Les noms de jeux de caractères devraient être enregistrés dans le registre IANA「Character Sets」(http://www.iana.org/assignments/character-sets) selon les procédures définies dans la Section 2 de [RFC2978].

Note : Le paramètre「charset」sur un type de média peut avoir une sémantique différente selon la définition spécifique du type de média.

Le paramètre「charset」est souvent utilisé avec des types de média pour le contenu textuel. Bien que les normes définissant ces types de média devraient prescrire l'utilisation d'un jeu de caractères particulier s'il est susceptible d'améliorer l'interopérabilité, les utilisateurs et les implémenteurs de HTTP sont fortement encouragés à spécifier explicitement un jeu de caractères lorsqu'il affecte l'interprétation du contenu reçu, même lorsque la définition du type de média par défaut utilise un jeu de caractères en l'absence du paramètre charset (comme c'est souvent le cas pour les types de média「text」).

8.3.3. Types Multipart (Multipart Types)

MIME fournit un certain nombre de types「multipart」-- encapsulations d'une ou plusieurs représentations dans un seul contenu de message. Tous les types multipart partagent une syntaxe commune, telle que définie dans la Section 5.1 de [RFC2046], et incluent un paramètre de limite dans le cadre de la valeur du type de média. Le contenu du message est lui-même un élément de protocole ; un expéditeur DOIT (MUST) générer uniquement CRLF pour représenter les sauts de ligne entre les parties du corps.

Le cadrage de message HTTP n'utilise pas la limite multipart comme indicateur de longueur du corps du message, bien qu'elle puisse être utilisée par les implémentations qui génèrent ou traitent le contenu. Par exemple, le type「multipart/form-data」est souvent utilisé pour transporter des données de formulaire dans une requête, comme décrit dans [RFC7578], et le type「multipart/byteranges」est défini par cette spécification pour une utilisation dans certaines réponses 206 (Partial Content) (voir Section 15.3.7).

8.4. Content-Encoding

Le champ d'en-tête「Content-Encoding」indique quels codages de contenu ont été appliqués à la représentation, au-delà de ceux inhérents au type de média, et donc quels mécanismes de décodage doivent être appliqués afin d'obtenir des données dans le type de média référencé par le champ d'en-tête Content-Type. Content-Encoding est principalement utilisé pour permettre la compression des données d'une représentation sans perdre l'identité de son type de média sous-jacent.

Content-Encoding = #content-coding

Un exemple de son utilisation est

Content-Encoding: gzip

Si un ou plusieurs encodages ont été appliqués à une représentation, l'expéditeur qui a appliqué les encodages DOIT (MUST) générer un champ d'en-tête Content-Encoding qui répertorie les codages de contenu dans l'ordre dans lequel ils ont été appliqués. Notez que le codage nommé「identity」est réservé pour son rôle spécial dans Accept-Encoding et NE DEVRAIT donc PAS (SHOULD NOT) être inclus.

Des informations supplémentaires sur les paramètres d'encodage peuvent être fournies par d'autres champs d'en-tête non définis par cette spécification.

Contrairement à Transfer-Encoding (Section 6.1 de [HTTP/1.1]), les codages répertoriés dans Content-Encoding sont une caractéristique de la représentation ; la représentation est définie en termes de forme codée, et toutes les autres métadonnées sur la représentation concernent la forme codée sauf indication contraire dans la définition des métadonnées. Typiquement, la représentation n'est décodée que juste avant le rendu ou une utilisation analogue.

Si le type de média inclut un encodage inhérent, tel qu'un format de données qui est toujours compressé, alors cet encodage ne serait pas réitéré dans Content-Encoding même s'il se trouve être le même algorithme que l'un des codages de contenu. Un tel codage de contenu ne serait répertorié que si, pour une raison bizarre, il est appliqué une seconde fois pour former la représentation. De même, un serveur d'origine peut choisir de publier les mêmes données sous forme de représentations multiples qui diffèrent uniquement par le fait que le codage est défini comme faisant partie de Content-Type ou Content-Encoding, car certains agents utilisateurs se comporteront différemment dans leur gestion de chaque réponse (par exemple, ouvrir une boîte de dialogue「Enregistrer sous...」au lieu d'une décompression et d'un rendu automatiques du contenu).

Un serveur d'origine PEUT (MAY) répondre avec un code d'état de 415 (Unsupported Media Type) si une représentation dans le message de requête a un codage de contenu qui n'est pas acceptable.

8.4.1. Codages de Contenu (Content Codings)

Les valeurs de codage de contenu indiquent une transformation d'encodage qui a été ou peut être appliquée à une représentation. Les codages de contenu sont principalement utilisés pour permettre la compression d'une représentation ou une transformation utile sans perdre l'identité de son type de média sous-jacent et sans perte d'informations. Fréquemment, la représentation est stockée sous forme codée, transmise directement, et décodée uniquement par le destinataire final.

content-coding   = token

Tous les codages de contenu sont insensibles à la casse et devraient être enregistrés dans le「Registre de Codage de Contenu HTTP」, tel que défini dans la Section 16.6.1. Ils sont utilisés dans les champs d'en-tête Accept-Encoding (Section 12.5.3) et Content-Encoding (Section 8.4).

Les codages de contenu suivants sont définis par cette spécification :

  • compress (et x-compress) : Voir Section 8.4.1.1.
  • deflate : Voir Section 8.4.1.2.
  • gzip (et x-gzip) : Voir Section 8.4.1.3.

8.4.1.1. Codage Compress

Le codage「compress」est un codage Lempel-Ziv-Welch (LZW) adaptatif [Welch] qui est couramment produit par le programme de compression de fichiers UNIX「compress」. Un destinataire DEVRAIT (SHOULD) considérer「x-compress」comme équivalent à「compress」.

8.4.1.2. Codage Deflate

Le codage「deflate」est un format de données「zlib」[RFC1950] contenant un flux de données compressé「deflate」[RFC1951] qui utilise une combinaison de l'algorithme de compression Lempel-Ziv (LZ77) et du codage Huffman.

Note : Certaines implémentations non conformes envoient les données compressées「deflate」sans l'enveloppe zlib.

8.4.1.3. Codage Gzip

Le codage「gzip」est un codage LZ77 avec un contrôle de redondance cyclique (CRC) de 32 bits qui est couramment produit par le programme de compression de fichiers gzip [RFC1952]. Un destinataire DEVRAIT (SHOULD) considérer「x-gzip」comme équivalent à「gzip」.

8.5. Content-Language

Le champ d'en-tête「Content-Language」décrit la ou les langues naturelles du public visé pour la représentation. Notez que cela peut ne pas être équivalent à toutes les langues utilisées dans la représentation.

Content-Language = #language-tag

Les balises de langue sont définies dans la Section 8.5.1. L'objectif principal de Content-Language est de permettre à un utilisateur d'identifier et de différencier les représentations selon les préférences linguistiques de l'utilisateur. Ainsi, si le contenu est destiné uniquement à un public qui lit le danois, le champ approprié est

Content-Language: da

Si aucun Content-Language n'est spécifié, la valeur par défaut est que le contenu est destiné à tous les publics linguistiques. Cela peut signifier que l'expéditeur ne le considère pas comme spécifique à une langue naturelle, ou que l'expéditeur ne sait pas pour quelle langue il est destiné.

Plusieurs langues PEUVENT (MAY) être répertoriées pour le contenu destiné à plusieurs publics. Par exemple, une représentation du「Traité de Waitangi」, présentée simultanément dans les versions originales maories et anglaises, nécessiterait

Content-Language: mi, en

Cependant, le simple fait que plusieurs langues soient présentes dans une représentation ne signifie pas qu'elle est destinée à plusieurs publics linguistiques. Un exemple serait un manuel de langue pour débutants, tel que「Une première leçon en latin」, qui est clairement destiné à être utilisé par un public qui lit l'anglais. Dans ce cas, Content-Language ne devrait inclure correctement que「en」.

Content-Language PEUT (MAY) être appliqué à n'importe quel type de média -- il n'est pas limité aux documents textuels.

8.5.1. Balises de Langue (Language Tags)

Une balise de langue, telle que définie dans [RFC5646], identifie une langue naturelle parlée, écrite ou autrement transmise par des êtres humains pour la communication d'informations à d'autres êtres humains. Les langages informatiques sont explicitement exclus.

HTTP utilise des balises de langue dans les champs d'en-tête Accept-Language et Content-Language. Accept-Language utilise la production language-range plus large définie dans la Section 12.5.4, tandis que Content-Language utilise la production language-tag définie ci-dessous.

language-tag = <Language-Tag, voir [RFC5646], Section 2.1>

Une balise de langue est une séquence d'une ou plusieurs sous-balises insensibles à la casse, chacune séparée par un caractère trait d'union ("-", %x2D). Dans la plupart des cas, une balise de langue se compose d'une sous-balise de langue primaire qui identifie une large famille de langues apparentées (par exemple,「en」= anglais) et est éventuellement suivie d'une série de sous-balises qui affinent ou restreignent la portée de cette langue (par exemple,「en-CA」= la variété d'anglais communiquée au Canada). L'espace blanc n'est pas autorisé dans une balise de langue. Voici quelques exemples de balises :

fr, en-US, es-419, az-Arab, x-pig-latin, man-Nkoo-GN

Voir [RFC5646] pour plus d'informations.

8.6. Content-Length

Le champ d'en-tête「Content-Length」indique la longueur des données de la représentation associée sous la forme d'un nombre entier décimal non négatif d'octets. Lors du transfert d'une représentation en tant que contenu, Content-Length se réfère spécifiquement à la quantité de données incluses afin qu'elle puisse être utilisée pour délimiter le cadrage (par exemple, Section 6.2 de [HTTP/1.1]). Dans d'autres cas où une représentation complète est attendue, Content-Length se réfère à la longueur actuellement sélectionnée de la représentation.

Content-Length = 1*DIGIT

Un exemple est

Content-Length: 3495

Un agent utilisateur DEVRAIT (SHOULD) envoyer Content-Length dans une requête lorsque la méthode définit une signification pour le contenu inclus et qu'il n'envoie pas Transfer-Encoding. Par exemple, un champ d'en-tête Content-Length est normalement envoyé dans une requête POST même lorsque la valeur est 0 (indiquant un contenu vide).

Un agent utilisateur NE DEVRAIT PAS (SHOULD NOT) envoyer un champ d'en-tête Content-Length lorsque le message de requête ne contient pas de contenu et que la sémantique de la méthode n'anticipe pas de telles données.

Un serveur PEUT (MAY) envoyer un champ d'en-tête Content-Length dans une réponse à une requête HEAD (Section 9.3.2) ; un serveur NE DOIT PAS (MUST NOT) envoyer Content-Length dans une telle réponse à moins que sa valeur de champ n'égale le nombre décimal d'octets qui auraient été envoyés dans le contenu d'une réponse si la même requête avait utilisé la méthode GET.

Un serveur PEUT (MAY) envoyer un champ d'en-tête Content-Length dans une réponse 304 (Not Modified) à une requête GET conditionnelle (Section 15.4.5) ; un serveur NE DOIT PAS (MUST NOT) envoyer Content-Length dans une telle réponse à moins que sa valeur de champ n'égale le nombre décimal d'octets qui auraient été envoyés dans le contenu d'une réponse 200 (OK) à la même requête.

Un serveur NE DOIT PAS (MUST NOT) envoyer un champ d'en-tête Content-Length dans une réponse avec un code d'état de 1xx (Informational) ou 204 (No Content). Un serveur NE DOIT PAS (MUST NOT) envoyer un champ d'en-tête Content-Length dans une réponse 2xx (Successful) à une requête CONNECT (Section 9.3.6).

En dehors des cas définis ci-dessus, en l'absence de Transfer-Encoding, un serveur d'origine DEVRAIT (SHOULD) envoyer un champ d'en-tête Content-Length lorsque la taille du contenu est connue avant d'envoyer la section d'en-tête complète. Cela permettra aux destinataires en aval de mesurer la progression du transfert, de connaître leurs propres limites de cadrage et de réutiliser la connexion pour les requêtes ultérieures.

Étant donné que Content-Length est utilisé pour la délimitation de message dans HTTP/1.1, sa valeur de champ peut affecter la manière dont le message est analysé par les destinataires même lorsque le cadrage du message n'est pas soumis aux règles HTTP/1.1. Si la valeur ne correspond pas à la longueur de données réelle de la représentation, les résultats peuvent aller d'un mauvais cadrage de message à une potentielle contrebande de requête ou division de réponse, selon les circonstances.

Un expéditeur NE DOIT PAS (MUST NOT) envoyer un champ d'en-tête Content-Length dans un message qui contient un champ d'en-tête Transfer-Encoding.

Note : L'utilisation de Content-Length par HTTP pour le cadrage de message diffère considérablement de l'utilisation du même champ dans MIME, où il s'agit d'un champ facultatif utilisé uniquement dans le type de média「message/external-body」.

8.7. Content-Location

Le champ d'en-tête「Content-Location」fait référence à un URI qui peut être utilisé comme identifiant pour une ressource spécifique correspondant à la représentation dans le contenu de ce message. En d'autres termes, si l'on devait effectuer une requête GET sur cet URI au moment de la génération de ce message, alors une réponse 200 (OK) contiendrait la même représentation qui est incluse en tant que contenu dans ce message.

Content-Location = absolute-URI / partial-URI

La valeur Content-Location n'est pas un remplacement de l'URI cible (Section 7.1). C'est une métadonnée de représentation. Elle a la même syntaxe et la même sémantique que le champ d'en-tête du même nom défini pour les parties du corps MIME dans la Section 4 de [RFC2557]. Cependant, son apparition dans un message HTTP a certaines implications spéciales pour les destinataires HTTP.

Si Content-Location est inclus dans un message de réponse 2xx (Successful) et que sa valeur fait référence à un URI avec le même schéma, autorité et chemin que l'URI cible, alors le destinataire PEUT (MAY) considérer le contenu comme une représentation actuelle de cette ressource cible. Pour une requête GET (Section 9.3.1) ou HEAD (Section 9.3.2), c'est la même chose que la sémantique par défaut lorsqu'aucun Content-Location n'est fourni par le serveur. Pour une requête de changement d'état comme PUT (Section 9.3.4) ou POST (Section 9.3.3), cela implique que le contenu de la réponse du serveur contient une représentation actuelle de cette ressource cible, la distinguant ainsi des représentations qui pourraient uniquement rapporter l'action (par exemple,「Ça a marché !」). Cela permet aux applications de création de mettre à jour leurs copies locales sans avoir besoin d'une requête GET ultérieure.

Si Content-Location est inclus dans un message de réponse 2xx (Successful) et que sa valeur de champ fait référence à un URI qui diffère de l'URI cible, alors le serveur d'origine affirme que l'URI est un identifiant pour une ressource différente correspondant à la représentation incluse. Une telle affirmation ne peut être considérée comme fiable que si les deux identifiants partagent le même propriétaire de ressource, ce qui ne peut pas être déterminé par programmation via HTTP.

  • Pour une réponse à une requête GET ou HEAD, c'est une indication que l'URI cible fait référence à une ressource soumise à la négociation de contenu et la valeur du champ Content-Location est un identifiant plus spécifique pour la représentation sélectionnée.

  • Pour une réponse 201 (Created) à une requête POST, la valeur du champ Content-Location est une référence à la ressource qui contient la représentation actuelle correspondant à la nouvelle ressource.

Sinon, un tel Content-Location indique que ce contenu est une représentation signalant le statut de l'action demandée et que le même rapport est disponible (pour un accès futur avec GET) à l'URI donné. Par exemple, une transaction d'achat effectuée via une requête POST peut inclure un document de reçu en tant que contenu de la réponse 200 (OK) ; la valeur du champ Content-Location fournit un identifiant pour récupérer une copie de ce même reçu à l'avenir.

Un agent utilisateur qui envoie Content-Location dans un message de requête indique que sa valeur fait référence à l'endroit où l'agent utilisateur a initialement obtenu le contenu de la représentation incluse (avant toute modification apportée par cet agent utilisateur). En d'autres termes, l'agent utilisateur fournit un lien retour vers la source de la représentation d'origine.

Un serveur d'origine qui reçoit un champ Content-Location dans un message de requête DOIT (MUST) traiter l'information comme un contexte de requête transitoire plutôt que comme des métadonnées à enregistrer avec la représentation. Un serveur d'origine PEUT (MAY) utiliser ce contexte pour guider le traitement de la requête ou pour l'enregistrer pour d'autres usages, tels que dans les liens sources ou les métadonnées de versionnage. Cependant, un serveur d'origine NE DOIT PAS (MUST NOT) utiliser ces informations de contexte pour modifier la sémantique de la requête.

Par exemple, si un client effectue une requête PUT sur une ressource négociée et que le serveur d'origine accepte ce PUT (sans redirection), alors le nouvel état de cette ressource devrait être cohérent avec la représentation unique fournie dans ce PUT ; Content-Location ne peut pas être utilisé comme une forme d'identifiant de sélection de contenu inversé pour mettre à jour uniquement l'une des représentations négociées. Si l'agent utilisateur voulait cette dernière sémantique, il aurait appliqué le PUT directement à l'URI Content-Location.

8.8. Champs de Validation (Validator Fields)

Les métadonnées de ressource sont appelées「validateur」si elles peuvent être utilisées dans une précondition (Section 13) pour effectuer une requête conditionnelle (Section 13.1).

Les champs de validation transmettent un validateur actuel pour la représentation sélectionnée (Section 3.2).

Dans les réponses aux requêtes sûres, les champs de validation décrivent la représentation sélectionnée (Section 3.2). Notez que, selon la sémantique du code d'état, la représentation sélectionnée pour une réponse donnée n'est pas nécessairement la même que la représentation incluse en tant que contenu de réponse.

Dans une réponse réussie à une requête de changement d'état, les champs de validation décrivent la nouvelle représentation qui a remplacé la représentation sélectionnée antérieure suite au traitement de la requête.

Par exemple, un champ d'en-tête ETag dans une réponse 201 (Created) communique un validateur pour la ressource créée par la requête, et un champ d'en-tête ETag dans une réponse 200 (OK) à PUT communique un validateur pour la nouvelle représentation qui a remplacé la représentation sélectionnée antérieure suite à la requête PUT.

Cette spécification définit deux formes de métadonnées couramment utilisées pour observer l'état de la ressource et tester les préconditions sur les requêtes : les dates de modification (Section 8.8.2) et les balises d'entité opaques (Section 8.8.3). Des informations supplémentaires sur diverses considérations de conception peuvent être trouvées dans la Section 13.2.

8.8.1. Faible versus Fort (Weak versus Strong)

Les validateurs existent en deux variétés : fort ou faible. Les validateurs faibles sont faciles à générer mais sont beaucoup moins utiles pour les comparaisons. Les validateurs forts sont idéaux pour les comparaisons mais peuvent être très difficiles (et parfois impossibles) à générer efficacement. Plutôt que d'imposer que toutes les formes de ressources adhèrent à la même force de validateur, HTTP expose le type de validateur en cours d'utilisation et impose des restrictions sur le moment où les validateurs faibles peuvent être utilisés comme préconditions.

Un「validateur fort」est une métadonnée de représentation qui change de valeur chaque fois qu'un changement se produit dans les données de représentation qui serait observable dans le contenu d'une réponse 200 (OK) à GET.

Un validateur fort peut changer pour des raisons autres qu'un changement dans les données de représentation, comme lorsqu'une partie sémantiquement significative des métadonnées de représentation est modifiée (par exemple, Content-Type), mais il est dans le meilleur intérêt du serveur d'origine de ne changer la valeur que lorsqu'il est nécessaire d'invalider les réponses stockées détenues par les caches distants et les outils de création.

Les entrées de cache peuvent persister pendant des périodes arbitrairement longues, indépendamment des temps d'expiration. Ainsi, un cache peut tenter de valider une entrée en utilisant un validateur qu'il a obtenu dans un passé lointain. Un validateur fort est unique à travers toutes les versions de toutes les représentations associées à une ressource particulière au fil du temps. Cependant, il n'y a pas d'implication d'unicité à travers les représentations de ressources différentes (c'est-à-dire que le même validateur fort peut être utilisé pour les représentations de plusieurs ressources en même temps et n'implique pas que ces représentations sont équivalentes).

Il existe une variété de validateurs forts utilisés en pratique. Les meilleurs sont basés sur un contrôle de révision strict, dans lequel chaque changement à une représentation entraîne toujours l'attribution d'un nom de nœud unique et d'un identifiant de révision avant que la représentation ne soit rendue accessible à GET. Une fonction de hachage résistante aux collisions appliquée aux données de représentation est également suffisante si les données sont disponibles avant l'envoi de la section d'en-tête de réponse et que le condensé n'a pas besoin d'être recalculé chaque fois qu'une requête de validation est reçue. Cependant, si une ressource a des représentations distinctes qui diffèrent uniquement par leurs métadonnées, comme cela pourrait se produire avec la négociation de contenu sur les types de médias qui partagent le même format de données, alors le serveur d'origine doit incorporer des informations supplémentaires dans le validateur pour distinguer ces représentations.

En revanche, un「validateur faible」est une métadonnée de représentation qui peut ne pas changer pour chaque changement dans les données de représentation. Cette faiblesse peut être due à des limitations dans la façon dont la valeur est calculée (par exemple, résolution d'horloge), à une incapacité à garantir l'unicité pour toutes les représentations possibles de la ressource, ou à un désir de regrouper les représentations par un ensemble d'équivalence auto-déterminé plutôt que par des séquences de données uniques.

Un serveur d'origine DEVRAIT (SHOULD) changer une balise d'entité faible chaque fois qu'il considère que les représentations antérieures ne sont pas acceptables en remplacement de la représentation actuelle. En d'autres termes, une balise d'entité faible devrait changer chaque fois que le serveur d'origine souhaite que les caches invalident les anciennes réponses.

Par exemple, la représentation d'un rapport météo qui change de contenu toutes les secondes, basé sur des mesures dynamiques, peut être regroupée en ensembles de représentations équivalentes (du point de vue du serveur d'origine) avec le même validateur faible afin de permettre aux représentations mises en cache d'être valides pendant une période raisonnable (peut-être ajustée dynamiquement en fonction de la charge du serveur ou de la qualité météorologique). De même, le temps de modification d'une représentation, s'il est défini avec une résolution d'une seule seconde, peut être un validateur faible s'il est possible que la représentation soit modifiée deux fois au cours d'une seule seconde et récupérée entre ces modifications.

De même, un validateur est faible s'il est partagé par deux ou plusieurs représentations d'une ressource donnée en même temps, à moins que ces représentations aient des données de représentation identiques. Par exemple, si le serveur d'origine envoie le même validateur pour une représentation avec un codage de contenu gzip appliqué que pour une représentation sans codage de contenu, alors ce validateur est faible. Cependant, deux représentations simultanées peuvent partager le même validateur fort si elles diffèrent uniquement dans les métadonnées de représentation, comme lorsque deux types de médias différents sont disponibles pour les mêmes données de représentation.

Les validateurs forts sont utilisables pour toutes les requêtes conditionnelles, y compris la validation de cache, les plages de contenu partiel et l'évitement de la「perte de mise à jour」. Les validateurs faibles ne sont utilisables que lorsque le client n'exige pas une égalité exacte avec les données de représentation précédemment obtenues, comme lors de la validation d'une entrée de cache ou de la limitation d'une traversée Web aux changements récents.

8.8.2. Last-Modified

Le champ d'en-tête「Last-Modified」dans une réponse fournit un horodatage indiquant la date et l'heure auxquelles le serveur d'origine croit que la représentation sélectionnée a été modifiée pour la dernière fois, tel que déterminé à la fin du traitement de la requête.

Last-Modified = HTTP-date

Un exemple de son utilisation est

Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT

8.8.2.1. Génération (Generation)

Un serveur d'origine DEVRAIT (SHOULD) envoyer Last-Modified pour toute représentation sélectionnée pour laquelle une date de dernière modification peut être raisonnablement et systématiquement déterminée, car son utilisation dans les requêtes conditionnelles et l'évaluation de la fraîcheur du cache ([CACHING]) peut réduire considérablement les transferts inutiles et améliorer significativement la disponibilité et l'évolutivité du service.

Une représentation est généralement la somme de nombreuses parties derrière l'interface de la ressource. Le temps de dernière modification serait généralement le moment le plus récent où l'une de ces parties a été modifiée. La façon dont cette valeur est déterminée pour une ressource donnée est un détail d'implémentation au-delà de la portée de cette spécification. Ce qui importe pour HTTP, c'est la façon dont les destinataires du champ d'en-tête Last-Modified peuvent utiliser sa valeur pour effectuer des requêtes conditionnelles et tester la validité des réponses mises en cache localement.

Un serveur d'origine DEVRAIT (SHOULD) obtenir la valeur Last-Modified de la représentation aussi près que possible du moment où il génère la valeur du champ Date pour sa réponse. Cela permet à un destinataire de faire une évaluation précise du temps de modification de la représentation, en particulier si la représentation change près du moment où la réponse est générée.

Un serveur d'origine avec une horloge (telle que définie dans la Section 5.6.7) NE DOIT PAS (MUST NOT) envoyer une date Last-Modified postérieure au temps d'origine du message du serveur (Date). Si le temps de dernière modification est dérivé de métadonnées spécifiques à l'implémentation qui évaluent à un moment futur, selon l'horloge du serveur d'origine, alors le serveur d'origine DOIT (MUST) remplacer cette valeur par la date d'origine du message. Cela empêche une date de modification future d'avoir un impact négatif sur la validation du cache.

Un serveur d'origine sans horloge NE DOIT PAS (MUST NOT) attribuer de valeurs Last-Modified à une réponse à moins que ces valeurs ne soient associées à la ressource par un autre système ou utilisateur avec une horloge fiable.

8.8.2.2. Comparaison (Comparison)

Un temps Last-Modified, lorsqu'il est utilisé comme validateur dans une requête, est implicitement faible à moins qu'il ne soit possible de déduire qu'il est fort, en utilisant les règles suivantes :

  • Le validateur est comparé par un serveur d'origine au validateur actuel réel de la représentation et,

  • Ce serveur d'origine sait de manière fiable que la représentation 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 champ d'en-tête If-Modified-Since, If-Unmodified-Since ou If-Range, car le client a une entrée de cache pour la représentation associée, et

  • Cette entrée de cache inclut une valeur Date, qui donne le moment où le serveur d'origine a envoyé la réponse d'origine, et

  • Le temps Last-Modified présenté est au moins 60 secondes avant la valeur Date.

ou

  • Le validateur est comparé par un cache intermédiaire au validateur stocké dans son entrée de cache pour la représentation, et

  • Cette entrée de cache inclut une valeur Date, qui donne le moment où le serveur d'origine a envoyé la réponse d'origine, et

  • Le temps Last-Modified présenté est au moins 60 secondes avant 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 les deux avaient le même temps Last-Modified, alors au moins une de ces réponses aurait une valeur Date égale à son temps Last-Modified. La limite arbitraire de 60 secondes protège 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, s'il est jugé que 60 secondes est trop court.

8.8.3. ETag

Le champ d'en-tête「ETag」dans une réponse fournit la balise d'entité actuelle pour la représentation sélectionnée, telle que déterminée à la fin du traitement de la requête. Une balise d'entité est un validateur opaque pour différencier entre plusieurs représentations de la même ressource, que ces multiples représentations soient dues à des changements d'état de la ressource au fil du temps, à la négociation de contenu entraînant plusieurs représentations valides en même temps, ou aux deux. Une balise d'entité se compose d'une chaîne opaque entre guillemets, éventuellement précédée d'un indicateur de faiblesse.

ETag       = entity-tag

entity-tag = [ weak ] opaque-tag
weak = %s"W/"
opaque-tag = DQUOTE *etagc DQUOTE
etagc = %x21 / %x23-7E / obs-text
; VCHAR sauf guillemets doubles, plus obs-text

Note : Auparavant, opaque-tag était défini comme étant une quoted-string ([RFC2616], Section 3.11) ; ainsi, certains destinataires peuvent effectuer un désechappement de barre oblique inverse. Les serveurs devraient donc éviter les caractères de barre oblique inverse dans les balises d'entité.

Une balise d'entité peut être plus fiable qu'une date de modification pour plusieurs raisons : il peut ne pas y avoir d'horloge disponible pour le serveur ; le temps de modification d'une ressource peut être défini dans le futur à des fins de contrôle d'accès ; la résolution d'un temps de modification est limitée par la façon dont il est stocké ; les systèmes distribués peuvent avoir des difficultés à synchroniser les horloges ; une balise d'entité peut incorporer des métadonnées supplémentaires, telles que la valeur d'un champ d'en-tête Content-Encoding, pour mieux distinguer les représentations ; et ainsi de suite.

Deux balises d'entité sont équivalentes si leurs opaque-tags correspondent caractère par caractère, indépendamment du fait que l'une ou l'autre soit marquée comme faible.

Une balise d'entité peut être soit un validateur fort, soit un validateur faible, le fort étant par défaut. Si un serveur d'origine fournit une balise d'entité pour une représentation et que la génération de cette balise d'entité ne satisfait pas toutes les caractéristiques d'un validateur fort (Section 8.8.1), alors le serveur d'origine DOIT (MUST) marquer la balise d'entité comme faible en préfixant sa valeur opaque avec「W/」(sensible à la casse).

ETag: W/"xyzzy"
ETag: ""

8.8.3.1. Génération (Generation)

Le principe derrière les balises d'entité est que seul l'auteur du service connaît suffisamment bien l'implémentation d'une ressource pour sélectionner le mécanisme de validation le plus précis et le plus efficace pour cette ressource, et que tout mécanisme de ce type peut être mappé à une simple séquence d'octets pour une comparaison facile. Puisque la valeur est opaque, le client n'a pas besoin de savoir comment chaque balise d'entité est construite.

Par exemple, une ressource qui a un versionnage spécifique à l'implémentation appliqué à tous les changements peut utiliser un numéro de révision interne, peut-être combiné avec un identifiant de variance pour la négociation de contenu, pour différencier avec précision les représentations. D'autres implémentations peuvent utiliser un hachage résistant aux collisions du contenu de la représentation, une combinaison de divers attributs de fichier, ou un horodatage de modification qui a une résolution inférieure à la seconde.

Un serveur d'origine DEVRAIT (SHOULD) envoyer un ETag pour toute représentation sélectionnée pour laquelle la détection des changements peut être raisonnablement et systématiquement déterminée, car l'utilisation de la balise d'entité dans les requêtes conditionnelles et l'évaluation de la fraîcheur du cache ([CACHING]) peut entraîner une réduction substantielle du trafic réseau HTTP et peut contribuer de manière significative à l'évolutivité et à la fiabilité du service.

8.8.3.2. Comparaison (Comparison)

Il existe deux fonctions de comparaison de balise d'entité, selon que le contexte de comparaison permet l'utilisation de validateurs faibles ou non :

  • Comparaison forte : deux balises d'entité sont équivalentes si elles ne sont pas toutes les deux faibles et que leurs opaque-tags correspondent caractère par caractère.

  • Comparaison faible : deux balises d'entité sont équivalentes si leurs opaque-tags correspondent caractère par caractère, indépendamment du fait que l'une ou l'autre soit marquée comme faible.

L'exemple ci-dessous montre les résultats pour un ensemble de paires de balises d'entité et les résultats des fonctions de comparaison faible et forte :

ETag 1ETag 2Comparaison forteComparaison faible
W/"1"W/"1"pas de correspondancecorrespondance
W/"1"W/"2"pas de correspondancepas de correspondance
W/"1""1"pas de correspondancecorrespondance
"1""1"correspondancecorrespondance

8.8.3.3. Exemple : Balises d'Entité Variant sur les Ressources Négociées en Contenu

Considérez une ressource soumise à la négociation de contenu (Section 12.1), et où les représentations envoyées en réponse à une requête GET varient en fonction du champ d'en-tête de requête Accept-Encoding (Section 12.5.3) :

>> Requête :

GET /index HTTP/1.1
Host: www.example.com
Accept-Encoding: gzip

>> Réponse :

HTTP/1.1 200 OK
Date: Fri, 26 Mar 2010 00:05:00 GMT
ETag: "123-a"
Content-Length: 70
Vary: Accept-Encoding
Content-Type: text/plain
Content-Encoding: gzip

[...]

Pour un ensemble différent de champs d'en-tête de requête, une représentation différente pourrait être envoyée par le serveur :

>> Requête :

GET /index HTTP/1.1
Host: www.example.com

>> Réponse :

HTTP/1.1 200 OK
Date: Fri, 26 Mar 2010 00:05:00 GMT
ETag: "123-b"
Content-Length: 400
Vary: Accept-Encoding
Content-Type: text/plain

[...]

La différence dans les balises d'entité dans ces deux réponses indique que les représentations envoyées contiennent des données différentes. Les balises d'entité fortes utilisées dans cette instance permettent l'utilisation de requêtes conditionnelles pour la validation du cache et les requêtes de plage.

En revanche, un serveur d'origine qui génère une représentation encodée en gzip à la volée, sans vérifier s'il existe une version antérieure de la représentation qui aurait déjà pu être générée, pourrait utiliser des balises d'entité faibles pour indiquer un contenu équivalent :

>> Réponse :

HTTP/1.1 200 OK
Date: Fri, 26 Mar 2010 00:05:00 GMT
ETag: W/"123"
Content-Length: 70
Vary: Accept-Encoding
Content-Type: text/plain
Content-Encoding: gzip

[...]

Dans ce cas, le serveur suppose que la version compressée de la représentation est équivalente à la version non compressée, tout en ne suivant pas suffisamment bien les versions pour déterminer le validateur fort.