Aller au contenu principal

3. Message Format

Tous les messages HTTP/1.1 se composent d'une ligne de départ suivie d'une séquence d'octets dans un format similaire à celui de l'Internet Message Format [RFC5322] : zéro ou plusieurs champs d'en-tête (collectivement appelés les « en-têtes » ou la « section d'en-tête »), une ligne vide indiquant la fin de la section d'en-tête, et un corps de message facultatif.

HTTP-message   = start-line
*( header-field CRLF )
CRLF
[ message-body ]

La procédure normale d'analyse d'un message HTTP consiste à lire la ligne de départ dans une structure, à lire chaque champ d'en-tête dans une table de hachage indexée par nom de champ jusqu'à la ligne vide, puis à utiliser les données analysées pour déterminer si un corps de message est attendu. Si un corps de message a été indiqué, il est alors lu comme un flux jusqu'à ce qu'un nombre d'octets égal à la longueur du corps de message ait été lu, ou jusqu'à ce que la connexion soit fermée.

Un destinataire MUST analyser un message HTTP comme une séquence d'octets dans un encodage qui est un sur-ensemble de l'US-ASCII [USASCII]. Analyser un message HTTP comme un flux de caractères Unicode, sans tenir compte de l'encodage particulier, crée des vulnérabilités de sécurité en raison des manières variables dont les bibliothèques de traitement de chaînes gèrent les séquences de caractères multioctets invalides contenant l'octet LF (%x0A). Les analyseurs fondés sur des chaînes ne peuvent être utilisés sans danger à l'intérieur d'éléments de protocole qu'après que l'élément a été extrait du message, par exemple à l'intérieur d'une field-value d'en-tête après que l'analyse du message a délimité les différents champs.

Un message HTTP peut être analysé comme un flux en vue d'un traitement incrémental ou d'un transfert vers l'aval. Cependant, les destinataires ne peuvent pas compter sur une livraison incrémentale de messages partiels, car certaines implémentations mettent en mémoire tampon ou retardent le transfert des messages pour des raisons d'efficacité réseau, de contrôles de sécurité ou de transformations de charge utile.

Un expéditeur MUST NOT envoyer d'espace blanc entre la ligne de départ et le premier champ d'en-tête. Un destinataire qui reçoit un espace blanc entre la ligne de départ et le premier champ d'en-tête MUST soit rejeter le message comme invalide, soit consommer chaque ligne précédée d'un espace blanc sans la traiter davantage (c'est-à-dire ignorer la ligne entière, ainsi que toutes les lignes suivantes précédées d'un espace blanc, jusqu'à ce qu'un champ d'en-tête correctement formé soit reçu ou que la section d'en-tête soit terminée).

La présence d'un tel espace blanc dans une requête peut être une tentative de tromper un serveur pour qu'il ignore ce champ ou qu'il traite la ligne suivante comme une nouvelle requête, ce qui pourrait, dans un cas comme dans l'autre, créer une vulnérabilité de sécurité si d'autres implémentations de la chaîne de requêtes interprètent le même message différemment. De même, la présence d'un tel espace blanc dans une réponse peut être ignorée par certains clients ou amener d'autres clients à cesser l'analyse.

3.1. Ligne de départ​

Un message HTTP peut être soit une requête d'un client vers un serveur, soit une réponse d'un serveur vers un client. Sur le plan syntaxique, les deux types de message ne diffèrent que par la ligne de départ, qui est soit une ligne de requête (pour les requêtes), soit une ligne d'état (pour les réponses), et par l'algorithme servant à déterminer la longueur du corps du message (Section 3.3).

En théorie, un client pourrait recevoir des requêtes et un serveur pourrait recevoir des réponses, en les distinguant par leurs formats de ligne de départ différents, mais, en pratique, les serveurs sont implémentés pour n'attendre qu'une requête (une réponse est interprétée comme une méthode de requête inconnue ou invalide) et les clients sont implémentés pour n'attendre qu'une réponse.

start-line     = request-line / status-line

3.1.1. Ligne de requête​

Une ligne de requête commence par un jeton de méthode, suivi d'un seul espace (SP), de la cible de requête, d'un autre espace simple (SP), de la version de protocole, et se termine par CRLF.

request-line   = method SP request-target SP HTTP-version CRLF

Le jeton de méthode indique la méthode de requête à appliquer à la ressource cible. La méthode de requête est sensible à la casse.

method         = token

Les méthodes de requête définies par cette spécification se trouvent à la Section 4 de [RFC7231], avec des informations concernant le registre des méthodes HTTP et des considérations pour la définition de nouvelles méthodes.

La cible de requête identifie la ressource cible à laquelle appliquer la requête, comme défini à la Section 5.3.

Les destinataires analysent typiquement la ligne de requête en ses parties constituantes en la découpant sur les espaces blancs (voir la Section 3.5), puisqu'aucun espace blanc n'est autorisé dans les trois composants. Malheureusement, certains agents utilisateurs échouent à encoder ou à exclure correctement les espaces blancs trouvés dans les références hypertexte, ce qui entraîne l'envoi de ces caractères interdits dans une cible de requête.

Les destinataires d'une ligne de requête invalide SHOULD répondre soit par une erreur 400 (Bad Request), soit par une redirection 301 (Moved Permanently) avec la cible de requête correctement encodée. Un destinataire SHOULD NOT tenter de corriger automatiquement puis de traiter la requête sans redirection, car la ligne de requête invalide peut avoir été délibérément forgée pour contourner les filtres de sécurité le long de la chaîne de requêtes.

HTTP n'impose pas de limite prédéfinie à la longueur d'une ligne de requête, comme décrit à la Section 2.5. Un serveur qui reçoit une méthode plus longue que toutes celles qu'il implémente SHOULD répondre par un code d'état 501 (Not Implemented). Un serveur qui reçoit une cible de requête plus longue que tout URI qu'il souhaite analyser MUST répondre par un code d'état 414 (URI Too Long) (voir la Section 6.5.12 de [RFC7231]).

Diverses limitations ad hoc sur la longueur de la ligne de requête se rencontrent en pratique. Il est RECOMMENDED que tous les expéditeurs et destinataires HTTP prennent en charge, au minimum, des longueurs de ligne de requête de 8000 octets.

3.1.2. Ligne d'état​

La première ligne d'un message de réponse est la ligne d'état, composée de la version de protocole, d'un espace (SP), du code d'état, d'un autre espace, d'une phrase textuelle éventuellement vide décrivant le code d'état, et se terminant par CRLF.

status-line = HTTP-version SP status-code SP reason-phrase CRLF

L'élément status-code est un code entier à 3 chiffres décrivant le résultat de la tentative du serveur de comprendre et de satisfaire la requête correspondante du client. Le reste du message de réponse doit être interprété à la lumière de la sémantique définie pour ce code d'état. Voir la Section 6 de [RFC7231] pour des informations sur la sémantique des codes d'état, y compris les classes de codes d'état (indiquées par le premier chiffre), les codes d'état définis par cette spécification, les considérations relatives à la définition de nouveaux codes d'état, et le registre IANA.

status-code    = 3DIGIT

L'élément reason-phrase n'existe que dans le seul but de fournir une description textuelle associée au code d'état numérique, principalement par déférence envers des protocoles applicatifs Internet plus anciens qui étaient plus souvent utilisés avec des clients textuels interactifs. Un client SHOULD ignorer le contenu de la reason-phrase.

reason-phrase  = *( HTAB / SP / VCHAR / obs-text )

3.2. Champs d'en-tête​

Chaque champ d'en-tête se compose d'un nom de champ insensible à la casse, suivi d'un deux-points (« : »), d'un espace blanc de début facultatif, de la valeur du champ, et d'un espace blanc de fin facultatif.

header-field   = field-name ":" OWS field-value OWS

field-name = token
field-value = *( field-content / obs-fold )
field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-vchar = VCHAR / obs-text

obs-fold = CRLF 1*( SP / HTAB )
; obsolete line folding
; see Section 3.2.4

Le jeton field-name étiquette la field-value correspondante comme ayant la sémantique définie par ce champ d'en-tête. Par exemple, le champ d'en-tête Date est défini à la Section 7.1.1.2 de [RFC7231] comme contenant l'horodatage d'origine du message dans lequel il apparaît.

3.2.1. Extensibilité des champs​

Les champs d'en-tête sont entièrement extensibles : il n'y a aucune limite à l'introduction de nouveaux noms de champ, dont chacun définit vraisemblablement une nouvelle sémantique, ni au nombre de champs d'en-tête utilisés dans un message donné. Les champs existants sont définis dans chaque partie de cette spécification et dans de nombreuses autres spécifications extérieures à cet ensemble de documents.

De nouveaux champs d'en-tête peuvent être définis de telle sorte que, lorsqu'ils sont compris par un destinataire, ils puissent remplacer ou enrichir l'interprétation de champs d'en-tête définis précédemment, définir des préconditions sur l'évaluation des requêtes, ou affiner la signification des réponses.

Un proxy MUST transférer les champs d'en-tête non reconnus, sauf si le field-name est listé dans le champ d'en-tête Connection (Section 6.1) ou si le proxy est spécifiquement configuré pour bloquer ou transformer de tels champs d'une autre manière. Les autres destinataires SHOULD ignorer les champs d'en-tête non reconnus. Ces exigences permettent d'enrichir les fonctionnalités de HTTP sans exiger une mise à jour préalable des intermédiaires déployés.

Tous les champs d'en-tête définis devraient être enregistrés auprès de l'IANA dans le registre « Message Headers », comme décrit à la Section 8.3 de [RFC7231].

3.2.2. Ordre des champs​

L'ordre dans lequel les champs d'en-tête ayant des noms de champ différents sont reçus n'est pas significatif. Cependant, il est de bonne pratique d'envoyer d'abord les champs d'en-tête qui contiennent des données de contrôle, tels que Host dans les requêtes et Date dans les réponses, afin que les implémentations puissent décider au plus tôt de ne pas traiter un message. Un serveur MUST NOT appliquer une requête à la ressource cible tant que la section d'en-tête complète de la requête n'a pas été reçue, car des champs d'en-tête ultérieurs peuvent inclure des conditions, des informations d'authentification, ou des champs d'en-tête en double délibérément trompeurs qui auraient une incidence sur le traitement de la requête.

Un expéditeur MUST NOT générer plusieurs champs d'en-tête ayant le même nom de champ dans un message, sauf si la valeur complète du champ pour ce champ d'en-tête est définie comme une liste séparée par des virgules [c'est-à-dire #(values)] ou si le champ d'en-tête constitue une exception bien connue (comme indiqué ci-dessous).

Un destinataire MAY combiner plusieurs champs d'en-tête ayant le même nom de champ en une seule paire « field-name: field-value », sans changer la sémantique du message, en ajoutant chacune des valeurs de champ suivantes à la valeur de champ combinée, dans l'ordre, séparées par une virgule. L'ordre dans lequel les champs d'en-tête ayant le même nom de champ sont reçus est donc significatif pour l'interprétation de la valeur de champ combinée ; un proxy MUST NOT changer l'ordre de ces valeurs de champ lorsqu'il transfère un message.

Note : en pratique, le champ d'en-tête « Set-Cookie » ([RFC6265]) apparaît souvent plusieurs fois dans un message de réponse et n'utilise pas la syntaxe de liste, ce qui viole les exigences ci-dessus concernant les champs d'en-tête multiples portant le même nom. Comme il ne peut pas être combiné en une seule field-value, les destinataires devraient traiter « Set-Cookie » comme un cas particulier lors du traitement des champs d'en-tête. (Voir la Section A.2.3 de [Kri2001] pour plus de détails.)

3.2.3. Espace blanc​

Cette spécification utilise trois règles pour désigner l'emploi d'espace blanc linéaire : OWS (espace blanc facultatif), RWS (espace blanc requis) et BWS (espace blanc « incorrect »).

La règle OWS est utilisée là où zéro ou plusieurs octets d'espace blanc linéaire peuvent apparaître. Pour les éléments de protocole où un espace blanc facultatif est préféré afin d'améliorer la lisibilité, un expéditeur SHOULD générer l'espace blanc facultatif sous la forme d'un seul SP ; sinon, un expéditeur SHOULD NOT générer d'espace blanc facultatif, sauf lorsque cela est nécessaire pour neutraliser des éléments de protocole invalides ou non désirés lors d'un filtrage de message sur place.

La règle RWS est utilisée lorsqu'au moins un octet d'espace blanc linéaire est requis pour séparer des jetons de champ. Un expéditeur SHOULD générer RWS sous la forme d'un seul SP.

La règle BWS est utilisée là où la grammaire n'autorise d'espace blanc facultatif que pour des raisons historiques. Un expéditeur MUST NOT générer de BWS dans les messages. Un destinataire MUST rechercher cet espace blanc incorrect et le supprimer avant d'interpréter l'élément de protocole.

OWS            = *( SP / HTAB )
; optional whitespace
RWS = 1*( SP / HTAB )
; required whitespace
BWS = OWS
; "bad" whitespace

3.2.4. Analyse des champs​

Les messages sont analysés à l'aide d'un algorithme générique, indépendant des différents noms de champs d'en-tête. Le contenu d'une valeur de champ donnée n'est pas analysé avant une étape ultérieure de l'interprétation du message (généralement après que toute la section d'en-tête du message a été traitée). Par conséquent, cette spécification n'utilise pas de règles ABNF pour définir chaque paire « Field-Name: Field Value », comme cela se faisait dans les éditions précédentes. Cette spécification utilise à la place des règles ABNF nommées d'après chaque nom de champ enregistré, la règle définissant la grammaire valide pour les valeurs de champ correspondant à ce champ (c'est-à-dire après que la field-value a été extraite de la section d'en-tête par un analyseur de champs générique).

Aucun espace blanc n'est autorisé entre le nom de champ d'en-tête et le deux-points. Par le passé, des différences dans le traitement de cet espace blanc ont conduit à des vulnérabilités de sécurité dans le routage des requêtes et le traitement des réponses. Un serveur MUST rejeter tout message de requête reçu qui contient un espace blanc entre un nom de champ d'en-tête et le deux-points, en répondant par le code 400 (Bad Request). Un proxy MUST supprimer tout espace blanc de ce type d'un message de réponse avant de le transférer vers l'aval.

Une valeur de champ peut être précédée et/ou suivie d'un espace blanc facultatif (OWS) ; un seul SP précédant la field-value est préféré pour une lisibilité homogène par les humains. La valeur de champ ne comprend aucun espace blanc de début ou de fin : l'OWS situé avant le premier octet non blanc de la valeur de champ ou après le dernier octet non blanc de la valeur de champ devrait être exclu par les analyseurs lorsqu'ils extraient la valeur de champ d'un champ d'en-tête.

Historiquement, les valeurs de champ d'en-tête HTTP pouvaient être étendues sur plusieurs lignes en faisant précéder chaque ligne supplémentaire d'au moins un espace ou une tabulation horizontale (obs-fold). Cette spécification rend obsolète ce repliement de lignes, sauf à l'intérieur du type de média message/http (Section 8.3.1). Un expéditeur MUST NOT générer un message qui comprend un repliement de lignes (c'est-à-dire dont une field-value quelconque correspond à la règle obs-fold), sauf si le message est destiné à être encapsulé dans le type de média message/http.

Un serveur qui reçoit un obs-fold dans un message de requête qui n'est pas à l'intérieur d'un conteneur message/http MUST soit rejeter le message en envoyant un 400 (Bad Request), de préférence avec une représentation expliquant que le repliement de lignes obsolète est inacceptable, soit remplacer chaque obs-fold reçu par un ou plusieurs octets SP avant d'interpréter la valeur de champ ou de transférer le message vers l'aval.

Un proxy ou une passerelle qui reçoit un obs-fold dans un message de réponse qui n'est pas à l'intérieur d'un conteneur message/http MUST soit écarter le message et le remplacer par une réponse 502 (Bad Gateway), de préférence avec une représentation expliquant qu'un repliement de lignes inacceptable a été reçu, soit remplacer chaque obs-fold reçu par un ou plusieurs octets SP avant d'interpréter la valeur de champ ou de transférer le message vers l'aval.

Un agent utilisateur qui reçoit un obs-fold dans un message de réponse qui n'est pas à l'intérieur d'un conteneur message/http MUST remplacer chaque obs-fold reçu par un ou plusieurs octets SP avant d'interpréter la valeur de champ.

Historiquement, HTTP a autorisé un contenu de champ comportant du texte dans le jeu de caractères ISO-8859-1 [ISO-8859-1], en ne prenant en charge d'autres jeux de caractères que par l'emploi de l'encodage [RFC2047]. En pratique, la plupart des valeurs de champ d'en-tête HTTP n'utilisent qu'un sous-ensemble du jeu de caractères US-ASCII [USASCII]. Les champs d'en-tête nouvellement définis SHOULD limiter leurs valeurs de champ à des octets US-ASCII. Un destinataire SHOULD traiter les autres octets du contenu de champ (obs-text) comme des données opaques.

3.2.5. Limites des champs​

HTTP n'impose pas de limite prédéfinie à la longueur de chaque champ d'en-tête ni à la longueur de la section d'en-tête dans son ensemble, comme décrit à la Section 2.5. Diverses limitations ad hoc sur la longueur d'un champ d'en-tête individuel se rencontrent en pratique, souvent en fonction de la sémantique particulière du champ.

Un serveur qui reçoit un champ d'en-tête de requête, ou un ensemble de champs, plus grand qu'il ne souhaite traiter MUST répondre par un code d'état 4xx (Client Error) approprié. Ignorer de tels champs d'en-tête augmenterait la vulnérabilité du serveur aux attaques par contrebande de requêtes (Section 9.5).

Un client MAY écarter ou tronquer les champs d'en-tête reçus qui sont plus grands que ce que le client souhaite traiter si la sémantique du champ est telle que la ou les valeurs supprimées peuvent être ignorées sans danger sans changer le cadrage du message ni la sémantique de la réponse.

3.2.6. Composants des valeurs de champ​

La plupart des valeurs de champ d'en-tête HTTP sont définies à l'aide de composants syntaxiques communs (token, quoted-string et comment) séparés par des espaces blancs ou des caractères délimiteurs particuliers. Les délimiteurs sont choisis dans l'ensemble des caractères visuels US-ASCII qui ne sont pas autorisés dans un token (DQUOTE et « (),/:;<=>?@[]{} »).

token          = 1*tchar

tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
/ "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
/ DIGIT / ALPHA
; any VCHAR, except delimiters

Une chaîne de texte est analysée comme une valeur unique si elle est mise entre guillemets doubles.

quoted-string  = DQUOTE *( qdtext / quoted-pair ) DQUOTE
qdtext = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
obs-text = %x80-FF

Des commentaires peuvent être inclus dans certains champs d'en-tête HTTP en entourant le texte du commentaire de parenthèses. Les commentaires ne sont autorisés que dans les champs contenant « comment » dans la définition de leur valeur de champ.

comment        = "(" *( ctext / quoted-pair / comment ) ")"
ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text

L'octet barre oblique inverse (« \ ») peut être utilisé comme mécanisme de citation sur un seul octet à l'intérieur des constructions quoted-string et comment. Les destinataires qui traitent la valeur d'un quoted-string MUST traiter un quoted-pair comme s'il était remplacé par l'octet suivant la barre oblique inverse.

quoted-pair    = "\" ( HTAB / SP / VCHAR / obs-text )

Un expéditeur SHOULD NOT générer de quoted-pair dans un quoted-string, sauf lorsque cela est nécessaire pour citer les octets DQUOTE et barre oblique inverse présents dans cette chaîne. Un expéditeur SHOULD NOT générer de quoted-pair dans un comment, sauf lorsque cela est nécessaire pour citer les parenthèses [« ( » et « ) »] et les octets barre oblique inverse présents dans ce commentaire.

3.3. Corps du message​

Le corps de message (s'il existe) d'un message HTTP sert à transporter le corps de charge utile de cette requête ou de cette réponse. Le corps de message est identique au corps de charge utile, sauf si un codage de transfert a été appliqué, comme décrit à la Section 3.3.1.

message-body = *OCTET

Les règles déterminant quand un corps de message est autorisé dans un message diffèrent selon qu'il s'agit d'une requête ou d'une réponse.

La présence d'un corps de message dans une requête est signalée par un champ d'en-tête Content-Length ou Transfer-Encoding. Le cadrage d'un message de requête est indépendant de la sémantique de la méthode, même si la méthode ne définit aucun usage pour un corps de message.

La présence d'un corps de message dans une réponse dépend à la fois de la méthode de la requête à laquelle elle répond et du code d'état de la réponse (Section 3.1.2). Les réponses à la méthode de requête HEAD (Section 4.3.2 de [RFC7231]) ne comportent jamais de corps de message, car les champs d'en-tête de réponse associés (par exemple Transfer-Encoding, Content-Length, etc.), s'ils sont présents, n'indiquent que ce qu'auraient été leurs valeurs si la méthode de requête avait été GET (Section 4.3.1 de [RFC7231]). Les réponses 2xx (Successful) à une méthode de requête CONNECT (Section 4.3.6 de [RFC7231]) basculent en mode tunnel plutôt que d'avoir un corps de message. Toutes les réponses 1xx (Informational), 204 (No Content) et 304 (Not Modified) ne comportent pas de corps de message. Toutes les autres réponses comportent un corps de message, bien que ce corps puisse être de longueur nulle.

3.3.1. Transfer-Encoding​

Le champ d'en-tête Transfer-Encoding énumère les noms de codage de transfert correspondant à la séquence de codages de transfert qui ont été (ou qui seront) appliqués au corps de charge utile afin de former le corps du message. Les codages de transfert sont définis à la Section 4.

Transfer-Encoding = 1#transfer-coding

Transfer-Encoding est analogue au champ Content-Transfer-Encoding de MIME, qui a été conçu pour permettre le transport sûr de données binaires sur un service de transport à 7 bits ([RFC2045], Section 6). Cependant, le transport sûr a une orientation différente pour un protocole de transfert compatible 8 bits. Dans le cas de HTTP, Transfer-Encoding vise principalement à délimiter avec précision une charge utile générée dynamiquement et à distinguer les encodages de charge utile qui ne sont appliqués que pour l'efficacité du transport ou la sécurité de ceux qui sont des caractéristiques de la ressource sélectionnée.

Un destinataire MUST être capable d'analyser le codage de transfert chunked (Section 4.1), car celui-ci joue un rôle crucial dans le cadrage des messages lorsque la taille du corps de charge utile n'est pas connue à l'avance. Un expéditeur MUST NOT appliquer chunked plus d'une fois à un corps de message (c'est-à-dire que découper en chunks un message déjà découpé n'est pas autorisé). Si un codage de transfert autre que chunked est appliqué à un corps de charge utile de requête, l'expéditeur MUST appliquer chunked comme dernier codage de transfert afin de garantir que le message est correctement cadré. Si un codage de transfert autre que chunked est appliqué à un corps de charge utile de réponse, l'expéditeur MUST soit appliquer chunked comme dernier codage de transfert, soit terminer le message en fermant la connexion.

Par exemple,

Transfer-Encoding: gzip, chunked

indique que le corps de charge utile a été compressé à l'aide du codage gzip, puis découpé en chunks à l'aide du codage chunked, lors de la formation du corps du message.

Contrairement à Content-Encoding (Section 3.1.2.1 de [RFC7231]), Transfer-Encoding est une propriété du message et non de la représentation, et tout destinataire le long de la chaîne requête/réponse MAY décoder le ou les codages de transfert reçus ou appliquer un ou plusieurs codages de transfert supplémentaires au corps du message, en supposant que les modifications correspondantes sont apportées à la field-value de Transfer-Encoding. 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.

Transfer-Encoding MAY être envoyé dans une réponse à une requête HEAD ou dans une réponse 304 (Not Modified) (Section 4.1 de [RFC7232]) à une requête GET, dont aucune ne comporte de corps de message, pour indiquer que le serveur d'origine aurait appliqué un codage de transfert au corps du message si la requête avait été un GET inconditionnel. Cette indication n'est toutefois pas requise, car tout destinataire de la chaîne de réponse (y compris le serveur d'origine) peut supprimer les codages de transfert lorsqu'ils ne sont pas nécessaires.

Un serveur MUST NOT envoyer de champ d'en-tête Transfer-Encoding dans une réponse dont le code d'état est 1xx (Informational) ou 204 (No Content). Un serveur MUST NOT envoyer de champ d'en-tête Transfer-Encoding dans une réponse 2xx (Successful) à une requête CONNECT (Section 4.3.6 de [RFC7231]).

Transfer-Encoding a été ajouté dans HTTP/1.1. On suppose généralement que les implémentations annonçant uniquement la prise en charge de HTTP/1.0 ne comprendront pas comment traiter une charge utile encodée en transfert. Un client MUST NOT envoyer de requête contenant Transfer-Encoding s'il ne sait pas que le serveur traitera les requêtes HTTP/1.1 (ou ultérieures) ; cette connaissance peut prendre la forme d'une configuration utilisateur particulière ou du souvenir de la version d'une réponse reçue antérieurement. Un serveur MUST NOT envoyer de réponse contenant Transfer-Encoding si la requête correspondante n'indique pas HTTP/1.1 (ou ultérieur).

Un serveur qui reçoit un message de requête comportant un codage de transfert qu'il ne comprend pas SHOULD répondre par 501 (Not Implemented).

3.3.2. Content-Length​

Lorsqu'un message ne comporte pas de champ d'en-tête Transfer-Encoding, un champ d'en-tête Content-Length peut fournir la taille anticipée, sous forme d'un nombre décimal d'octets, d'un éventuel corps de charge utile. Pour les messages qui comportent effectivement un corps de charge utile, la field-value de Content-Length fournit les informations de cadrage nécessaires pour déterminer où le corps (et le message) se termine. Pour les messages qui ne comportent pas de corps de charge utile, Content-Length indique la taille de la représentation sélectionnée (Section 3 de [RFC7231]).

Content-Length = 1*DIGIT

Un exemple est

Content-Length: 3495

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

Un agent utilisateur SHOULD envoyer un Content-Length dans un message de requête lorsqu'aucun Transfer-Encoding n'est envoyé et que la méthode de requête définit une signification pour un corps de charge utile inclus. 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 corps de charge utile vide). Un agent utilisateur SHOULD NOT envoyer de champ d'en-tête Content-Length lorsque le message de requête ne contient pas de corps de charge utile et que la sémantique de la méthode n'en prévoit pas.

Un serveur MAY envoyer un champ d'en-tête Content-Length dans une réponse à une requête HEAD (Section 4.3.2 de [RFC7231]) ; un serveur MUST NOT envoyer de Content-Length dans une telle réponse, sauf si sa field-value est égale au nombre décimal d'octets qui auraient été envoyés dans le corps de charge utile d'une réponse si la même requête avait utilisé la méthode GET.

Un serveur MAY envoyer un champ d'en-tête Content-Length dans une réponse 304 (Not Modified) à une requête GET conditionnelle (Section 4.1 de [RFC7232]) ; un serveur MUST NOT envoyer de Content-Length dans une telle réponse, sauf si sa field-value est égale au nombre décimal d'octets qui auraient été envoyés dans le corps de charge utile d'une réponse 200 (OK) à la même requête.

Un serveur MUST NOT envoyer de champ d'en-tête Content-Length dans une réponse dont le code d'état est 1xx (Informational) ou 204 (No Content). Un serveur MUST NOT envoyer de champ d'en-tête Content-Length dans une réponse 2xx (Successful) à une requête CONNECT (Section 4.3.6 de [RFC7231]).

En dehors des cas définis ci-dessus, en l'absence de Transfer-Encoding, un serveur d'origine SHOULD envoyer un champ d'en-tête Content-Length lorsque la taille du corps de charge utile est connue avant l'envoi de la section d'en-tête complète. Cela permet aux destinataires en aval de mesurer la progression du transfert, de savoir quand un message reçu est complet, et de réutiliser éventuellement la connexion pour des requêtes supplémentaires.

Toute valeur de champ Content-Length supérieure ou égale à zéro est valide. Comme il n'existe aucune limite prédéfinie à la longueur d'une charge utile, un destinataire MUST anticiper des nombres décimaux potentiellement grands et empêcher les erreurs d'analyse dues à des débordements de conversion d'entiers (Section 9.3).

Si un message est reçu avec plusieurs champs d'en-tête Content-Length dont les field-values consistent en la même valeur décimale, ou avec un seul champ d'en-tête Content-Length dont la valeur de champ contient une liste de valeurs décimales identiques (par exemple « Content-Length: 42, 42 »), ce qui indique que des champs d'en-tête Content-Length en double ont été générés ou combinés par un processeur de messages en amont, alors le destinataire MUST soit rejeter le message comme invalide, soit remplacer les field-values dupliquées par un seul champ Content-Length valide contenant cette valeur décimale, avant de déterminer la longueur du corps du message ou de transférer le message.

Note : l'usage que fait HTTP de Content-Length pour le cadrage des messages diffère sensiblement de l'usage du même champ dans MIME, où il s'agit d'un champ facultatif utilisé uniquement à l'intérieur du type de média « message/external-body ».

3.3.3. Longueur du corps du message​

La longueur d'un corps de message est déterminée par l'un des éléments suivants (par ordre de priorité) :

  1. Toute réponse à une requête HEAD et toute réponse dont le code d'état est 1xx (Informational), 204 (No Content) ou 304 (Not Modified) est toujours terminée par la première ligne vide après les champs d'en-tête, quels que soient les champs d'en-tête présents dans le message, et ne peut donc pas contenir de corps de message.

  2. Toute réponse 2xx (Successful) à une requête CONNECT implique que la connexion deviendra un tunnel immédiatement après la ligne vide qui conclut les champs d'en-tête. Un client MUST ignorer tout champ d'en-tête Content-Length ou Transfer-Encoding reçu dans un tel message.

  3. Si un champ d'en-tête Transfer-Encoding est présent et que le codage de transfert chunked (Section 4.1) est le codage final, la longueur du corps du message est déterminée en lisant et en décodant les données chunked jusqu'à ce que le codage de transfert indique que les données sont complètes.

Si un champ d'en-tête Transfer-Encoding est présent dans une réponse et que le codage de transfert chunked n'est pas le codage final, la longueur du corps du message est déterminée en lisant la connexion jusqu'à ce qu'elle soit fermée par le serveur. Si un champ d'en-tête Transfer-Encoding est présent dans une requête et que le codage de transfert chunked n'est pas le codage final, la longueur du corps du message ne peut pas être déterminée de manière fiable ; le serveur MUST répondre par le code d'état 400 (Bad Request), puis fermer la connexion.

Si un message est reçu avec à la fois un champ d'en-tête Transfer-Encoding et un champ d'en-tête Content-Length, Transfer-Encoding a priorité sur Content-Length. Un tel message peut indiquer une tentative de contrebande de requêtes (Section 9.5) ou de division de réponse (Section 9.4) et devrait être traité comme une erreur. Un expéditeur MUST supprimer le champ Content-Length reçu avant de transférer un tel message vers l'aval.

  1. Si un message est reçu sans Transfer-Encoding et avec soit plusieurs champs d'en-tête Content-Length ayant des field-values différentes, soit un seul champ d'en-tête Content-Length ayant une valeur invalide, alors le cadrage du message est invalide et le destinataire MUST le traiter comme une erreur irrécupérable. S'il s'agit d'un message de requête, le serveur MUST répondre par le code d'état 400 (Bad Request), puis fermer la connexion. S'il s'agit d'un message de réponse reçu par un proxy, le proxy MUST fermer la connexion au serveur, écarter la réponse reçue, et envoyer une réponse 502 (Bad Gateway) au client. S'il s'agit d'un message de réponse reçu par un agent utilisateur, l'agent utilisateur MUST fermer la connexion au serveur et écarter la réponse reçue.

  2. Si un champ d'en-tête Content-Length valide est présent sans Transfer-Encoding, sa valeur décimale définit la longueur attendue du corps du message en octets. Si l'expéditeur ferme la connexion ou si le destinataire dépasse le délai avant que le nombre d'octets indiqué n'ait été reçu, le destinataire MUST considérer le message comme incomplet et fermer la connexion.

  3. S'il s'agit d'un message de requête et qu'aucun des cas ci-dessus ne s'applique, alors la longueur du corps du message est nulle (aucun corps de message n'est présent).

  4. Sinon, il s'agit d'un message de réponse dont la longueur du corps du message n'est pas déclarée ; la longueur du corps du message est alors déterminée par le nombre d'octets reçus avant que le serveur ne ferme la connexion.

Comme il n'existe aucun moyen de distinguer un message correctement achevé et délimité par fermeture d'un message partiellement reçu et interrompu par une défaillance réseau, un serveur SHOULD générer des messages encodés ou délimités par une longueur chaque fois que cela est possible. La délimitation par fermeture existe principalement pour la rétrocompatibilité avec HTTP/1.0.

Un serveur MAY rejeter une requête qui contient un corps de message mais pas de Content-Length en répondant par 411 (Length Required).

Sauf si un codage de transfert autre que chunked a été appliqué, un client qui envoie une requête contenant un corps de message SHOULD utiliser un champ d'en-tête Content-Length valide si la longueur du corps du message est connue à l'avance, plutôt que le codage de transfert chunked, car certains services existants répondent à chunked par un code d'état 411 (Length Required) même s'ils comprennent le codage de transfert chunked. C'est généralement parce que ces services sont implémentés via une passerelle qui exige une content-length avant d'être appelée, et que le serveur est incapable ou ne souhaite pas mettre en mémoire tampon toute la requête avant de la traiter.

Un agent utilisateur qui envoie une requête contenant un corps de message MUST envoyer un champ d'en-tête Content-Length valide s'il ne sait pas que le serveur traitera les requêtes HTTP/1.1 (ou ultérieures) ; cette connaissance peut prendre la forme d'une configuration utilisateur particulière ou du souvenir de la version d'une réponse reçue antérieurement.

Si la réponse finale à la dernière requête d'une connexion a été complètement reçue et qu'il reste des données supplémentaires à lire, un agent utilisateur MAY écarter les données restantes ou tenter de déterminer si ces données font partie du corps de la réponse précédente, ce qui peut être le cas si la valeur de Content-Length du message précédent est incorrecte. Un client MUST NOT traiter, mettre en cache ni transférer ces données supplémentaires comme une réponse distincte, car un tel comportement serait vulnérable à un empoisonnement de cache.

3.4. Traitement des messages incomplets​

Un serveur qui reçoit un message de requête incomplet, généralement en raison d'une requête annulée ou d'une exception de délai d'attente déclenchée, MAY envoyer une réponse d'erreur avant de fermer la connexion.

Un client qui reçoit un message de réponse incomplet, ce qui peut se produire lorsqu'une connexion est fermée prématurément ou lorsque le décodage d'un codage de transfert censé être chunked échoue, MUST enregistrer le message comme incomplet. Les exigences relatives à la mise en cache des réponses incomplètes sont définies à la Section 3 de [RFC7234].

Si une réponse se termine au milieu de la section d'en-tête (avant que la ligne vide ne soit reçue) et que le code d'état peut dépendre de champs d'en-tête pour transmettre le sens complet de la réponse, alors le client ne peut pas supposer que ce sens a été transmis ; le client peut avoir besoin de répéter la requête afin de déterminer quelle action entreprendre ensuite.

Un corps de message qui utilise le codage de transfert chunked est incomplet si le chunk de taille nulle qui termine l'encodage n'a pas été reçu. Un message qui utilise un Content-Length valide est incomplet si la taille du corps de message reçu (en octets) est inférieure à la valeur donnée par Content-Length. Une réponse qui ne comporte ni codage de transfert chunked ni Content-Length est terminée par la fermeture de la connexion et, par conséquent, est considérée comme complète quel que soit le nombre d'octets de corps de message reçus, à condition que la section d'en-tête ait été reçue intacte.

3.5. Robustesse de l'analyse des messages​

Des implémentations plus anciennes d'agents utilisateurs HTTP/1.0 peuvent envoyer un CRLF supplémentaire après une requête POST, en guise de contournement pour certaines applications serveur précoces qui échouaient à lire le contenu d'un corps de message non terminé par un fin de ligne. Un agent utilisateur HTTP/1.1 MUST NOT faire précéder une requête d'un CRLF supplémentaire ni la faire suivre d'un tel CRLF. Si l'on souhaite terminer le corps du message de requête par un fin de ligne, l'agent utilisateur MUST compter les octets CRLF terminaux comme faisant partie de la longueur du corps du message.

Dans un souci de robustesse, un serveur qui s'attend à recevoir et à analyser une ligne de requête SHOULD ignorer au moins une ligne vide (CRLF) reçue avant la ligne de requête.

Bien que le terminateur de ligne de la ligne de départ et des champs d'en-tête soit la séquence CRLF, un destinataire MAY reconnaître un LF seul comme terminateur de ligne et ignorer tout CR qui le précède.

Bien que les règles de grammaire de la ligne de requête et de la ligne d'état exigent que chacun des éléments composants soit séparé par un seul octet SP, les destinataires MAY plutôt analyser selon des frontières de mots délimitées par des espaces blancs et, en dehors du terminateur CRLF, traiter toute forme d'espace blanc comme le séparateur SP tout en ignorant les espaces blancs de début ou de fin ; ces espaces blancs comprennent un ou plusieurs des octets suivants : SP, HTAB, VT (%x0B), FF (%x0C) ou CR nu. Cependant, une analyse permissive peut entraîner des vulnérabilités de sécurité s'il existe plusieurs destinataires du message et que chacun a sa propre interprétation de la robustesse (voir la Section 9.5).

Lorsqu'un serveur qui n'écoute que des messages de requête HTTP, ou qui traite ce qui semble être, d'après la ligne de départ, un message de requête HTTP, reçoit une séquence d'octets qui ne correspond pas à la grammaire HTTP-message en dehors des exceptions de robustesse énumérées ci-dessus, le serveur SHOULD répondre par une réponse 400 (Bad Request).