6. Abstraction des Messages (Message Abstraction)
Chaque version majeure de HTTP définit sa propre syntaxe pour communiquer les messages. Cette section définit un type de données abstrait pour les messages HTTP basé sur une généralisation de ces caractéristiques de message, de leur structure commune et de leur capacité à transmettre la sémantique. Cette abstraction est utilisée pour définir des exigences sur les émetteurs et les destinataires qui sont indépendantes de la version HTTP, de sorte qu'un message dans une version puisse être relayé via d'autres versions sans changer sa signification.
Un "message" (message) se compose des éléments suivants :
-
des données de contrôle pour décrire et acheminer le message,
-
une table de recherche d'en-têtes de paires nom/valeur pour étendre ces données de contrôle et transmettre des informations supplémentaires sur l'émetteur, le message, le contenu ou le contexte,
-
un flux de contenu potentiellement illimité, et
-
une table de recherche de trailers de paires nom/valeur pour communiquer les informations obtenues lors de l'envoi du contenu.
L'encadrement et les données de contrôle sont envoyés en premier, suivis d'une section d'en-tête contenant des champs pour la table d'en-têtes. Lorsqu'un message inclut du contenu, le contenu est envoyé après la section d'en-tête, potentiellement suivi d'une section de trailer qui peut contenir des champs pour la table de trailers.
Les messages sont censés être traités comme un flux, où le but de ce flux et son traitement continu sont révélés pendant la lecture. Par conséquent, les données de contrôle décrivent ce que le destinataire doit savoir immédiatement, les champs d'en-tête décrivent ce qui doit être connu avant de recevoir le contenu, le contenu (lorsqu'il est présent) contient vraisemblablement ce que le destinataire veut ou a besoin pour remplir la sémantique du message, et les champs de trailer fournissent des métadonnées optionnelles qui étaient inconnues avant d'envoyer le contenu.
Les messages sont destinés à être "auto-descriptifs" (self-descriptive) : tout ce qu'un destinataire doit savoir sur le message peut être déterminé en regardant le message lui-même, après avoir décodé ou reconstitué les parties qui ont été compressées ou élidées en transit, sans nécessiter une compréhension de l'état actuel de l'application de l'émetteur (établi via des messages antérieurs). Cependant, un client DOIT (MUST) conserver la connaissance de la requête lors de l'analyse, de l'interprétation ou de la mise en cache d'une réponse correspondante. Par exemple, les réponses à la méthode HEAD ressemblent au début d'une réponse à GET mais ne peuvent pas être analysées de la même manière.
Notez que cette abstraction de message est une généralisation sur de nombreuses versions de HTTP, incluant des fonctionnalités qui peuvent ne pas être trouvées dans certaines versions. Par exemple, les trailers ont été introduits dans le codage de transfert chunked HTTP/1.1 comme une section de trailer après le contenu. Une fonctionnalité équivalente est présente dans HTTP/2 et HTTP/3 dans le bloc d'en-tête qui termine chaque flux.
6.1. Encadrement et Complétude (Framing and Completeness)
L'encadrement des messages (Message framing) indique comment chaque message commence et se termine, de sorte que chaque message puisse être distingué des autres messages ou du bruit sur la même connexion. Chaque version majeure de HTTP définit son propre mécanisme d'encadrement.
HTTP/0.9 et les premiers déploiements de HTTP/1.0 utilisaient la fermeture de la connexion sous-jacente pour terminer une réponse. Pour la compatibilité ascendante, cet encadrement implicite est également autorisé dans HTTP/1.1. Cependant, l'encadrement implicite peut ne pas distinguer une réponse incomplète si la connexion se ferme prématurément. Pour cette raison, presque toutes les implémentations modernes utilisent un encadrement explicite sous la forme de séquences de données de message délimitées par la longueur.
Un message est considéré comme "complet" (complete) lorsque tous les octets indiqués par son encadrement sont disponibles. Notez que, lorsqu'aucun encadrement explicite n'est utilisé, un message de réponse qui est terminé par la fermeture de la connexion sous-jacente est considéré comme complet même s'il peut être impossible à distinguer d'une réponse incomplète, à moins qu'une erreur au niveau du transport n'indique qu'il n'est pas complet.
6.2. Données de Contrôle (Control Data)
Les messages commencent par des données de contrôle qui décrivent leur objectif principal. Les données de contrôle d'un message de requête incluent une méthode de requête (request method) (Section 9), une cible de requête (request target) (Section 7.1) et une version de protocole (protocol version) (Section 2.5). Les données de contrôle d'un message de réponse incluent un code d'état (status code) (Section 15), une phrase de raison (reason phrase) optionnelle et une version de protocole.
Dans HTTP/1.1 ([HTTP/1.1]) et versions antérieures, les données de contrôle sont envoyées comme première ligne d'un message. Dans HTTP/2 ([HTTP/2]) et HTTP/3 ([HTTP/3]), les données de contrôle sont envoyées comme champs pseudo-en-tête avec un préfixe de nom réservé (par exemple, ":authority").
Chaque message HTTP a une version de protocole. Selon la version utilisée, elle peut être identifiée explicitement dans le message ou déduite de la connexion sur laquelle le message est reçu. Les destinataires utilisent cette information de version pour déterminer les limitations ou le potentiel pour les communications ultérieures avec cet émetteur.
Lorsqu'un message est transféré par un intermédiaire, la version du protocole est mise à jour pour refléter la version utilisée par cet intermédiaire. Le champ d'en-tête Via (Section 7.6.3) est utilisé pour communiquer les informations de protocole en amont dans un message transféré.
Un client DEVRAIT (SHOULD) envoyer une version de requête égale à la version la plus élevée à laquelle le client est conforme et dont la version majeure n'est pas supérieure à la version la plus élevée prise en charge par le serveur, si cela est connu. Un client NE DOIT PAS (MUST NOT) envoyer une version à laquelle il n'est pas conforme.
Un client PEUT (MAY) envoyer une version de requête inférieure s'il est connu que le serveur implémente incorrectement la spécification HTTP, mais seulement après que le client ait tenté au moins une requête normale et déterminé à partir du code d'état de réponse ou des champs d'en-tête (par exemple, Server) que le serveur gère mal les versions de requête supérieures.
Un serveur DEVRAIT (SHOULD) envoyer une version de réponse égale à la version la plus élevée à laquelle le serveur est conforme et qui a une version majeure inférieure ou égale à celle reçue dans la requête. Un serveur NE DOIT PAS (MUST NOT) envoyer une version à laquelle il n'est pas conforme. Un serveur peut envoyer une réponse 505 (HTTP Version Not Supported) s'il souhaite, pour quelque raison que ce soit, refuser le service de la version majeure du protocole du client.
Un destinataire qui reçoit un message avec un numéro de version majeure qu'il implémente et un numéro de version mineure supérieur à ce qu'il implémente DEVRAIT (SHOULD) traiter le message comme s'il était dans la version mineure la plus élevée au sein de cette version majeure à laquelle le destinataire est conforme. Un destinataire peut supposer qu'un message avec une version mineure supérieure, lorsqu'il est envoyé à un destinataire qui n'a pas encore indiqué le support de cette version supérieure, est suffisamment rétrocompatible pour être traité en toute sécurité par toute implémentation de la même version majeure.
6.3. Champs d'En-tête (Header Fields)
Les champs (Section 5) qui sont envoyés ou reçus avant le contenu sont appelés "champs d'en-tête" (header fields) (ou simplement "en-têtes" (headers) familièrement).
La "section d'en-tête" (header section) d'un message se compose d'une séquence de lignes de champ d'en-tête. Chaque champ d'en-tête peut modifier ou étendre la sémantique du message, décrire l'émetteur, définir le contenu ou fournir un contexte supplémentaire.
Note : Nous faisons référence aux champs nommés spécifiquement comme "champ d'en-tête" lorsqu'ils ne sont autorisés à être envoyés que dans la section d'en-tête.
6.4. Contenu (Content)
Les messages HTTP transfèrent souvent une représentation complète ou partielle comme "contenu" (content) du message : un flux d'octets envoyé après la section d'en-tête, tel que délimité par l'encadrement du message.
Cette définition abstraite du contenu reflète les données après qu'elles ont été extraites de l'encadrement du message. Par exemple, un corps de message HTTP/1.1 (Section 6 de [HTTP/1.1]) peut consister en un flux de données encodé avec le codage de transfert chunked -- une séquence de morceaux de données, un morceau de longueur zéro et une section de trailer -- alors que le contenu de ce même message inclut uniquement le flux de données après que le codage de transfert a été décodé ; il n'inclut pas les longueurs de morceaux, la syntaxe d'encadrement chunked, ni les champs de trailer (Section 6.5).
Note : Certains noms de champs ont un préfixe "Content-". Il s'agit d'une convention informelle ; bien que certains de ces champs se réfèrent au contenu du message, tel que défini ci-dessus, d'autres sont limités à la représentation sélectionnée (Section 3.2). Consultez la définition du champ individuel pour lever l'ambiguïté.
6.4.1. Sémantique du Contenu (Content Semantics)
Le but du contenu dans une requête est défini par la sémantique de la méthode (Section 9).
Par exemple, une représentation dans le contenu d'une requête PUT (Section 9.3.4) représente l'état souhaité de la ressource cible après que la requête soit appliquée avec succès, alors qu'une représentation dans le contenu d'une requête POST (Section 9.3.3) représente des informations à traiter par la ressource cible.
Dans une réponse, le but du contenu est défini par la méthode de requête, le code d'état de réponse (Section 15) et les champs de réponse décrivant ce contenu. Par exemple, le contenu d'une réponse 200 (OK) à GET (Section 9.3.1) représente l'état actuel de la ressource cible, tel qu'observé au moment de la date d'origine du message (Section 6.6.1), alors que le contenu du même code d'état dans une réponse à POST peut représenter soit le résultat du traitement, soit le nouvel état de la ressource cible après application du traitement.
Le contenu d'une réponse 206 (Partial Content) à GET contient soit une seule partie de la représentation sélectionnée, soit un corps de message multipartie contenant plusieurs parties de cette représentation, comme décrit dans la Section 15.3.7.
Les messages de réponse avec un code d'état d'erreur contiennent généralement du contenu qui représente la condition d'erreur, de sorte que le contenu décrit l'état d'erreur et les étapes suggérées pour le résoudre.
Les réponses à la méthode de requête HEAD (Section 9.3.2) n'incluent jamais de contenu ; les champs d'en-tête de réponse associés indiquent uniquement ce que leurs valeurs auraient été si la méthode de requête avait été GET (Section 9.3.1).
Les réponses 2xx (Successful) à une méthode de requête CONNECT (Section 9.3.6) basculent la connexion en mode tunnel au lieu d'avoir du contenu.
Toutes les réponses 1xx (Informational), 204 (No Content) et 304 (Not Modified) n'incluent pas de contenu.
Toutes les autres réponses incluent du contenu, bien que ce contenu puisse être de longueur zéro.
6.4.2. Identification du Contenu (Identifying Content)
Lorsqu'une représentation complète ou partielle est transférée comme contenu de message, il est souvent souhaitable pour l'émetteur de fournir, ou pour le destinataire de déterminer, un identifiant pour une ressource correspondant à cette représentation spécifique. Par exemple, un client faisant une requête GET sur une ressource pour "le bulletin météorologique actuel" pourrait vouloir un identifiant spécifique au contenu retourné (par exemple, "bulletin météorologique pour Laguna Beach le 20210720T1711"). Cela peut être utile pour partager ou mettre en signet du contenu de ressources qui sont censées avoir des représentations changeantes au fil du temps.
Pour un message de requête :
-
Si la requête a un champ d'en-tête Content-Location, alors l'émetteur affirme que le contenu est une représentation de la ressource identifiée par la valeur du champ Content-Location. Cependant, une telle affirmation ne peut être considérée comme fiable que si elle peut être vérifiée par d'autres moyens (non définis par cette spécification). L'information peut toujours être utile pour les liens d'historique de révision.
-
Sinon, le contenu n'est pas identifié par HTTP, mais un identifiant plus spécifique peut être fourni dans le contenu lui-même.
Pour un message de réponse, les règles suivantes sont appliquées dans l'ordre jusqu'à ce qu'une correspondance soit trouvée :
-
Si la méthode de requête est HEAD ou si le code d'état de réponse est 204 (No Content) ou 304 (Not Modified), il n'y a pas de contenu dans la réponse.
-
Si la méthode de requête est GET et que le code d'état de réponse est 200 (OK), le contenu est une représentation de la ressource cible (Section 7.1).
-
Si la méthode de requête est GET et que le code d'état de réponse est 203 (Non-Authoritative Information), le contenu est une représentation potentiellement modifiée ou améliorée de la ressource cible telle que fournie par un intermédiaire.
-
Si la méthode de requête est GET et que le code d'état de réponse est 206 (Partial Content), le contenu est une ou plusieurs parties d'une représentation de la ressource cible.
-
Si la réponse a un champ d'en-tête Content-Location et que sa valeur de champ est une référence à la même URI que l'URI cible, le contenu est une représentation de la ressource cible.
-
Si la réponse a un champ d'en-tête Content-Location et que sa valeur de champ est une référence à une URI différente de l'URI cible, alors l'émetteur affirme que le contenu est une représentation de la ressource identifiée par la valeur du champ Content-Location. Cependant, une telle affirmation ne peut être considérée comme fiable que si elle peut être vérifiée par d'autres moyens (non définis par cette spécification).
-
Sinon, le contenu n'est pas identifié par HTTP, mais un identifiant plus spécifique peut être fourni dans le contenu lui-même.
6.5. Champs de Trailer (Trailer Fields)
Les champs (Section 5) qui sont situés dans une "section de trailer" (trailer section) sont appelés "champs de trailer" (trailer fields) (ou simplement "trailers" familièrement). Les champs de trailer peuvent être utiles pour fournir des vérifications d'intégrité de message, des signatures numériques, des métriques de livraison ou des informations d'état post-traitement.
Les champs de trailer devraient être traités et stockés séparément des champs dans la section d'en-tête pour éviter de contredire la sémantique du message connue au moment où la section d'en-tête était complète. La présence ou l'absence de certains champs d'en-tête peut avoir un impact sur les choix faits pour le routage ou le traitement du message dans son ensemble avant que les trailers ne soient reçus ; ces choix ne peuvent pas être annulés par la découverte ultérieure de champs de trailer.
6.5.1. Limitations sur l'Utilisation des Trailers (Limitations on Use of Trailers)
Une section de trailer n'est possible que lorsqu'elle est prise en charge par la version de HTTP utilisée et activée par un mécanisme d'encadrement explicite. Par exemple, le codage de transfert chunked dans HTTP/1.1 permet d'envoyer une section de trailer après le contenu (Section 7.1.2 de [HTTP/1.1]).
De nombreux champs ne peuvent pas être traités en dehors de la section d'en-tête car leur évaluation est nécessaire avant de recevoir le contenu, comme ceux qui décrivent l'encadrement du message, le routage, l'authentification, les modificateurs de requête, les contrôles de réponse ou le format de contenu. Un émetteur NE DOIT PAS (MUST NOT) générer un champ de trailer à moins que l'émetteur ne sache que la définition du nom de champ d'en-tête correspondant permet d'envoyer le champ dans les trailers.
Les champs de trailer peuvent être difficiles à traiter par les intermédiaires qui transfèrent des messages d'une version de protocole à une autre. Si le message entier peut être mis en mémoire tampon en transit, certains intermédiaires pourraient fusionner les champs de trailer dans la section d'en-tête (selon le cas) avant qu'il ne soit transféré. Cependant, dans la plupart des cas, les trailers sont simplement supprimés. Un destinataire NE DOIT PAS (MUST NOT) fusionner un champ de trailer dans une section d'en-tête à moins que le destinataire ne comprenne la définition du champ d'en-tête correspondant et que cette définition ne permette explicitement et ne définisse comment les valeurs de champ de trailer peuvent être fusionnées en toute sécurité.
La présence du mot-clé "trailers" dans le champ d'en-tête TE (Section 10.1.4) d'une requête indique que le client est prêt à accepter des champs de trailer, pour lui-même et pour tous les clients en aval. Pour les requêtes d'un intermédiaire, cela implique que tous les clients en aval sont prêts à accepter des champs de trailer dans la réponse transférée. Notez que la présence de "trailers" ne signifie pas que le(s) client(s) traitera(ont) un champ de trailer particulier dans la réponse ; seulement que la ou les sections de trailer ne seront pas abandonnées par l'un des clients.
En raison du potentiel de suppression des champs de trailer en transit, un serveur NE DEVRAIT PAS (SHOULD NOT) générer des champs de trailer qu'il croit nécessaires pour que l'agent utilisateur les reçoive.
6.5.2. Traitement des Champs de Trailer (Processing Trailer Fields)
Le champ d'en-tête "Trailer" (Section 6.6.2) peut être envoyé pour indiquer les champs susceptibles d'être envoyés dans la section de trailer, ce qui permet aux destinataires de se préparer à leur réception avant de traiter le contenu. Par exemple, cela pourrait être utile si un nom de champ indique qu'une somme de contrôle dynamique doit être calculée au fur et à mesure que le contenu est reçu, puis immédiatement vérifiée lors de la réception de la valeur du champ de trailer.
Comme les champs d'en-tête, les champs de trailer portant le même nom sont traités dans l'ordre de réception ; plusieurs lignes de champ de trailer avec le même nom ont la sémantique équivalente à l'ajout des valeurs multiples comme une liste de membres. Les champs de trailer qui pourraient être générés plus d'une fois pendant un message DOIVENT (MUST) être définis comme un champ basé sur une liste, même si chaque valeur de membre n'est traitée qu'une seule fois par ligne de champ reçue.
À la fin d'un message, un destinataire PEUT (MAY) traiter l'ensemble des champs de trailer reçus comme une structure de données de paires nom/valeur, similaire (mais séparée) aux champs d'en-tête. Des attentes de traitement supplémentaires, le cas échéant, peuvent être définies dans la spécification du champ pour un champ destiné à être utilisé dans les trailers.
6.6. Métadonnées du Message (Message Metadata)
Les champs qui décrivent le message lui-même, tels que quand et comment le message a été généré, peuvent apparaître dans les requêtes et les réponses.
6.6.1. Date
Le champ d'en-tête "Date" représente la date et l'heure auxquelles le message a été créé, ayant la même sémantique que le champ Date d'origine (orig-date) défini dans la Section 3.6.1 de [RFC5322]. La valeur du champ est une HTTP-date, telle que définie dans la Section 5.6.7.
Date = HTTP-date
Un exemple est :
Date: Tue, 15 Nov 1994 08:12:31 GMT
Un émetteur qui génère un champ d'en-tête Date DEVRAIT (SHOULD) générer sa valeur de champ comme la meilleure approximation disponible de la date et de l'heure de génération du message. En théorie, la date devrait représenter le moment juste avant de générer le contenu du message. En pratique, un émetteur peut générer la valeur de date à tout moment pendant l'origine du message.
Un serveur d'origine avec une horloge (telle que définie dans la Section 5.6.7) DOIT (MUST) générer un champ d'en-tête Date dans toutes les réponses 2xx (Successful), 3xx (Redirection) et 4xx (Client Error), et PEUT (MAY) générer un champ d'en-tête Date dans les réponses 1xx (Informational) et 5xx (Server Error).
Un serveur d'origine sans horloge NE DOIT PAS (MUST NOT) générer un champ d'en-tête Date.
Un destinataire avec une horloge qui reçoit un message de réponse sans champ d'en-tête Date DOIT (MUST) enregistrer l'heure à laquelle il a été reçu et ajouter un champ d'en-tête Date correspondant à la section d'en-tête du message s'il est mis en cache ou transféré en aval.
Un destinataire avec une horloge qui reçoit une réponse avec une valeur de champ d'en-tête Date invalide PEUT (MAY) remplacer cette valeur par l'heure à laquelle cette réponse a été reçue.
Un agent utilisateur PEUT (MAY) envoyer un champ d'en-tête Date dans une requête, bien qu'il ne le fasse généralement pas à moins qu'il ne soit jugé transmettre des informations utiles au serveur. Par exemple, des applications personnalisées de HTTP pourraient transmettre une Date si le serveur est censé ajuster son interprétation de la requête de l'utilisateur en fonction des différences entre les horloges de l'agent utilisateur et du serveur.
6.6.2. Trailer
Le champ d'en-tête "Trailer" fournit une liste de noms de champs que l'émetteur anticipe d'envoyer comme champs de trailer dans ce message. Cela permet à un destinataire de se préparer à la réception des métadonnées indiquées avant de commencer à traiter le contenu.
Trailer = #field-name
Par exemple, un émetteur pourrait indiquer qu'une signature sera calculée au fur et à mesure que le contenu est diffusé en continu et fournir la signature finale comme champ de trailer. Cela permet à un destinataire d'effectuer la même vérification à la volée au fur et à mesure qu'il reçoit le contenu.
Un émetteur qui a l'intention de générer un ou plusieurs champs de trailer dans un message DEVRAIT (SHOULD) générer un champ d'en-tête Trailer dans la section d'en-tête de ce message pour indiquer quels champs pourraient être présents dans les trailers.
Si un intermédiaire supprime la section de trailer en transit, le champ Trailer pourrait fournir un indice des métadonnées qui ont été perdues, bien qu'il n'y ait aucune garantie qu'un émetteur de Trailer ira toujours jusqu'au bout en envoyant les champs nommés.