Passa al contenuto principale

3. Formato dei messaggi

Tutti i messaggi HTTP/1.1 sono costituiti da una start-line seguita da una sequenza di ottetti in un formato simile all'Internet Message Format [RFC5322]: zero o più campi di intestazione (collettivamente indicati come "headers" o "sezione di intestazione"), una riga vuota che indica la fine della sezione di intestazione, e un corpo del messaggio opzionale.

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

La procedura normale per l'analisi di un messaggio HTTP consiste nel leggere la start-line in una struttura, nel leggere ciascun campo di intestazione in una tabella hash per nome di campo fino alla riga vuota, e quindi nell'usare i dati analizzati per determinare se è atteso un corpo del messaggio. Se è stato indicato un corpo del messaggio, esso viene letto come flusso finché non viene letta una quantità di ottetti pari alla lunghezza del corpo del messaggio o finché la connessione non viene chiusa.

Un destinatario MUST analizzare un messaggio HTTP come sequenza di ottetti in una codifica che sia un sovrainsieme di US-ASCII [USASCII]. Analizzare un messaggio HTTP come flusso di caratteri Unicode, senza riguardo per la specifica codifica, crea vulnerabilità di sicurezza a causa dei diversi modi in cui le librerie di elaborazione delle stringhe gestiscono sequenze di caratteri multibyte non valide che contengono l'ottetto LF (%x0A). I parser basati su stringhe possono essere usati in modo sicuro solo all'interno di elementi di protocollo dopo che l'elemento è stato estratto dal messaggio, ad esempio all'interno di un field-value di un campo di intestazione dopo che l'analisi del messaggio ha delimitato i singoli campi.

Un messaggio HTTP può essere analizzato come flusso per un'elaborazione incrementale o per l'inoltro a valle. Tuttavia, i destinatari non possono fare affidamento sulla consegna incrementale di messaggi parziali, poiché alcune implementazioni memorizzano nel buffer o ritardano l'inoltro dei messaggi per motivi di efficienza di rete, controlli di sicurezza o trasformazioni del payload.

Un mittente MUST NOT inviare spazi bianchi tra la start-line e il primo campo di intestazione. Un destinatario che riceve spazi bianchi tra la start-line e il primo campo di intestazione MUST o rifiutare il messaggio come non valido, oppure consumare ogni riga preceduta da spazi bianchi senza ulteriore elaborazione di essa (cioè ignorare l'intera riga, insieme a tutte le righe successive precedute da spazi bianchi, finché non viene ricevuto un campo di intestazione correttamente formato o finché la sezione di intestazione non viene terminata).

La presenza di tali spazi bianchi in una richiesta potrebbe essere un tentativo di indurre un server a ignorare quel campo o a elaborare la riga successiva come una nuova richiesta; entrambe le cose potrebbero comportare una vulnerabilità di sicurezza se altre implementazioni all'interno della catena di richieste interpretano lo stesso messaggio in modo diverso. Allo stesso modo, la presenza di tali spazi bianchi in una risposta potrebbe essere ignorata da alcuni client o indurre altri a interrompere l'analisi.

3.1. Start line​

Un messaggio HTTP può essere una richiesta da client a server oppure una risposta da server a client. Dal punto di vista sintattico, i due tipi di messaggio differiscono solo nella start-line, che è una request-line (per le richieste) o una status-line (per le risposte), e nell'algoritmo per determinare la lunghezza del corpo del messaggio (Sezione 3.3).

In teoria, un client potrebbe ricevere richieste e un server potrebbe ricevere risposte, distinguendole in base ai loro diversi formati di start-line, ma in pratica i server sono implementati per attendersi solo una richiesta (una risposta viene interpretata come un metodo di richiesta sconosciuto o non valido) e i client sono implementati per attendersi solo una risposta.

start-line     = request-line / status-line

3.1.1. Request line​

Una request-line inizia con un token method, seguito da un singolo spazio (SP), dal request-target, da un altro singolo spazio (SP), dalla versione del protocollo, e termina con CRLF.

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

Il token method indica il metodo di richiesta da eseguire sulla risorsa di destinazione. Il metodo di richiesta è sensibile alle maiuscole.

method         = token

I metodi di richiesta definiti da questa specifica si trovano nella Sezione 4 di [RFC7231], insieme alle informazioni sul registro dei metodi HTTP e alle considerazioni per la definizione di nuovi metodi.

Il request-target identifica la risorsa di destinazione alla quale applicare la richiesta, come definito nella Sezione 5.3.

I destinatari in genere analizzano la request-line nelle sue parti componenti suddividendola sugli spazi bianchi (vedere la Sezione 3.5), poiché nei tre componenti non è consentito alcuno spazio bianco. Sfortunatamente, alcuni user agent non riescono a codificare o escludere correttamente gli spazi bianchi presenti nei riferimenti ipertestuali, con il risultato che tali caratteri non consentiti vengono inviati in un request-target.

I destinatari di una request-line non valida SHOULD rispondere con un errore 400 (Bad Request) oppure con un reindirizzamento 301 (Moved Permanently) con il request-target codificato correttamente. Un destinatario SHOULD NOT tentare di correggere automaticamente e poi elaborare la richiesta senza un reindirizzamento, poiché la request-line non valida potrebbe essere creata deliberatamente per aggirare i filtri di sicurezza lungo la catena di richieste.

HTTP non impone un limite predefinito alla lunghezza di una request-line, come descritto nella Sezione 2.5. Un server che riceve un metodo più lungo di qualsiasi metodo che implementa SHOULD rispondere con un codice di stato 501 (Not Implemented). Un server che riceve un request-target più lungo di qualsiasi URI che intenda analizzare MUST rispondere con un codice di stato 414 (URI Too Long) (vedere la Sezione 6.5.12 di [RFC7231]).

In pratica si riscontrano varie limitazioni ad hoc sulla lunghezza della request-line. È RECOMMENDED che tutti i mittenti e i destinatari HTTP supportino, come minimo, lunghezze della request-line di 8000 ottetti.

3.1.2. Status line​

La prima riga di un messaggio di risposta è la status-line, che consiste nella versione del protocollo, uno spazio (SP), il codice di stato, un altro spazio, una frase testuale che descrive il codice di stato (che può essere vuota), e termina con CRLF.

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

L'elemento status-code è un codice intero di 3 cifre che descrive il risultato del tentativo del server di comprendere e soddisfare la corrispondente richiesta del client. Il resto del messaggio di risposta deve essere interpretato alla luce della semantica definita per quel codice di stato. Vedere la Sezione 6 di [RFC7231] per informazioni sulla semantica dei codici di stato, incluse le classi di codice di stato (indicate dalla prima cifra), i codici di stato definiti da questa specifica, le considerazioni per la definizione di nuovi codici di stato e il registro IANA.

status-code    = 3DIGIT

L'elemento reason-phrase esiste al solo scopo di fornire una descrizione testuale associata al codice di stato numerico, soprattutto per deferenza verso i primi protocolli applicativi Internet che venivano usati più spesso con client testuali interattivi. Un client SHOULD ignorare il contenuto della reason-phrase.

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

3.2. Campi di intestazione​

Ogni campo di intestazione è costituito da un nome di campo che non distingue maiuscole e minuscole, seguito da due punti (":"), da spazi bianchi iniziali opzionali, dal valore del campo e da spazi bianchi finali opzionali.

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

Il token field-name etichetta il corrispondente field-value come avente la semantica definita da quel campo di intestazione. Ad esempio, il campo di intestazione Date è definito nella Sezione 7.1.1.2 di [RFC7231] come contenente il timestamp di creazione del messaggio in cui appare.

3.2.1. Estensibilità dei campi​

I campi di intestazione sono completamente estensibili: non vi è alcun limite all'introduzione di nuovi nomi di campo, ciascuno dei quali presumibilmente definisce nuova semantica, né al numero di campi di intestazione usati in un dato messaggio. I campi esistenti sono definiti in ogni parte di questa specifica e in molte altre specifiche al di fuori di questo insieme di documenti.

Nuovi campi di intestazione possono essere definiti in modo tale che, quando vengono compresi da un destinatario, possano sovrascrivere o migliorare l'interpretazione di campi di intestazione definiti in precedenza, definire precondizioni sulla valutazione della richiesta, oppure perfezionare il significato delle risposte.

Un proxy MUST inoltrare i campi di intestazione non riconosciuti, a meno che il field-name non sia elencato nel campo di intestazione Connection (Sezione 6.1) o il proxy non sia specificamente configurato per bloccare, o altrimenti trasformare, tali campi. Gli altri destinatari SHOULD ignorare i campi di intestazione non riconosciuti. Questi requisiti consentono di migliorare le funzionalità di HTTP senza richiedere un aggiornamento preventivo degli intermediari già distribuiti.

Tutti i campi di intestazione definiti dovrebbero essere registrati presso l'IANA nel registro "Message Headers", come descritto nella Sezione 8.3 di [RFC7231].

3.2.2. Ordine dei campi​

L'ordine in cui vengono ricevuti i campi di intestazione con nomi di campo diversi non è significativo. Tuttavia, è buona pratica inviare per primi i campi di intestazione che contengono dati di controllo, come Host nelle richieste e Date nelle risposte, in modo che le implementazioni possano decidere il prima possibile quando non gestire un messaggio. Un server MUST NOT applicare una richiesta alla risorsa di destinazione finché non è stata ricevuta l'intera sezione di intestazione della richiesta, poiché campi di intestazione successivi potrebbero includere condizionali, credenziali di autenticazione o campi di intestazione duplicati deliberatamente fuorvianti che influenzerebbero l'elaborazione della richiesta.

Un mittente MUST NOT generare più campi di intestazione con lo stesso nome di campo in un messaggio, a meno che l'intero valore di campo di quel campo di intestazione non sia definito come elenco separato da virgole [cioè #(values)] oppure il campo di intestazione non sia una nota eccezione (come osservato di seguito).

Un destinatario MAY combinare più campi di intestazione con lo stesso nome di campo in un'unica coppia "field-name: field-value", senza modificare la semantica del messaggio, aggiungendo ciascun valore di campo successivo al valore di campo combinato, in ordine, separato da una virgola. L'ordine in cui vengono ricevuti i campi di intestazione con lo stesso nome di campo è quindi significativo per l'interpretazione del valore di campo combinato; un proxy MUST NOT cambiare l'ordine di questi valori di campo quando inoltra un messaggio.

Nota: in pratica, il campo di intestazione "Set-Cookie" ([RFC6265]) appare spesso più volte in un messaggio di risposta e non usa la sintassi di elenco, violando i requisiti sopra esposti relativi ai più campi di intestazione con lo stesso nome. Poiché non può essere combinato in un unico field-value, i destinatari dovrebbero gestire "Set-Cookie" come caso speciale durante l'elaborazione dei campi di intestazione. (Vedere l'Appendice A.2.3 di [Kri2001] per i dettagli.)

3.2.3. Spazi bianchi​

Questa specifica usa tre regole per denotare l'uso di spazi bianchi lineari: OWS (optional whitespace), RWS (required whitespace) e BWS ("bad" whitespace).

La regola OWS è usata dove possono comparire zero o più ottetti di spazio bianco lineare. Per gli elementi di protocollo in cui si preferiscono spazi bianchi opzionali per migliorare la leggibilità, un mittente SHOULD generare gli spazi bianchi opzionali come un singolo SP; in caso contrario, un mittente SHOULD NOT generare spazi bianchi opzionali, se non nella misura necessaria a cancellare elementi di protocollo non validi o indesiderati durante il filtraggio in place dei messaggi.

La regola RWS è usata quando è richiesto almeno un ottetto di spazio bianco lineare per separare i token di campo. Un mittente SHOULD generare RWS come un singolo SP.

La regola BWS è usata dove la grammatica consente spazi bianchi opzionali solo per ragioni storiche. Un mittente MUST NOT generare BWS nei messaggi. Un destinatario MUST verificare la presenza di tali spazi bianchi non validi e rimuoverli prima di interpretare l'elemento di protocollo.

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

3.2.4. Analisi dei campi​

I messaggi vengono analizzati tramite un algoritmo generico, indipendente dai singoli nomi dei campi di intestazione. Il contenuto all'interno di un dato valore di campo non viene analizzato finché non si giunge a una fase successiva dell'interpretazione del messaggio (di solito dopo che l'intera sezione di intestazione del messaggio è stata elaborata). Di conseguenza, questa specifica non usa regole ABNF per definire ogni coppia "Field-Name: Field Value", come si faceva nelle edizioni precedenti. Questa specifica usa invece regole ABNF denominate in base a ciascun nome di campo registrato, in cui la regola definisce la grammatica valida per i corrispondenti valori di campo di quel campo (cioè dopo che il field-value è stato estratto dalla sezione di intestazione da un parser di campi generico).

Non è consentito alcuno spazio bianco tra il field-name del campo di intestazione e i due punti. In passato, differenze nella gestione di tali spazi bianchi hanno portato a vulnerabilità di sicurezza nell'instradamento delle richieste e nella gestione delle risposte. Un server MUST rifiutare qualsiasi messaggio di richiesta ricevuto che contenga spazi bianchi tra un field-name e i due punti, con un codice di risposta 400 (Bad Request). Un proxy MUST rimuovere tali spazi bianchi da un messaggio di risposta prima di inoltrarlo a valle.

Un valore di campo può essere preceduto e/o seguito da spazi bianchi opzionali (OWS); un singolo SP che precede il field-value è preferito per una leggibilità coerente da parte degli esseri umani. Il valore del campo non include spazi bianchi iniziali o finali: gli OWS che compaiono prima del primo ottetto non di spazio bianco del valore del campo o dopo l'ultimo ottetto non di spazio bianco del valore del campo dovrebbero essere esclusi dai parser quando estraggono il valore del campo da un campo di intestazione.

Storicamente, i valori dei campi di intestazione HTTP potevano essere estesi su più righe facendo precedere ogni riga aggiuntiva da almeno uno spazio o una tabulazione orizzontale (obs-fold). Questa specifica depreca tale ripiegamento di riga, tranne che all'interno del media type message/http (Sezione 8.3.1). Un mittente MUST NOT generare un messaggio che includa il ripiegamento di riga (cioè che abbia un qualsiasi field-value che contenga una corrispondenza con la regola obs-fold), a meno che il messaggio non sia destinato all'incapsulamento all'interno del media type message/http.

Un server che riceve un obs-fold in un messaggio di richiesta che non si trova all'interno di un contenitore message/http MUST o rifiutare il messaggio inviando un 400 (Bad Request), preferibilmente con una rappresentazione che spieghi che il ripiegamento di riga obsoleto non è accettabile, oppure sostituire ciascun obs-fold ricevuto con uno o più ottetti SP prima di interpretare il valore del campo o di inoltrare il messaggio a valle.

Un proxy o gateway che riceve un obs-fold in un messaggio di risposta che non si trova all'interno di un contenitore message/http MUST o scartare il messaggio e sostituirlo con una risposta 502 (Bad Gateway), preferibilmente con una rappresentazione che spieghi che è stato ricevuto un ripiegamento di riga non accettabile, oppure sostituire ciascun obs-fold ricevuto con uno o più ottetti SP prima di interpretare il valore del campo o di inoltrare il messaggio a valle.

Uno user agent che riceve un obs-fold in un messaggio di risposta che non si trova all'interno di un contenitore message/http MUST sostituire ciascun obs-fold ricevuto con uno o più ottetti SP prima di interpretare il valore del campo.

Storicamente, HTTP ha consentito contenuti di campo con testo nel charset ISO-8859-1 [ISO-8859-1], supportando altri charset solo tramite l'uso della codifica [RFC2047]. In pratica, la maggior parte dei valori dei campi di intestazione HTTP usa solo un sottoinsieme del charset US-ASCII [USASCII]. I campi di intestazione di nuova definizione SHOULD limitare i propri valori di campo agli ottetti US-ASCII. Un destinatario SHOULD trattare gli altri ottetti nel contenuto del campo (obs-text) come dati opachi.

3.2.5. Limiti dei campi​

HTTP non impone un limite predefinito alla lunghezza di ciascun campo di intestazione né alla lunghezza della sezione di intestazione nel suo complesso, come descritto nella Sezione 2.5. In pratica si riscontrano varie limitazioni ad hoc sulla lunghezza dei singoli campi di intestazione, spesso in funzione della specifica semantica del campo.

Un server che riceve un campo di intestazione della richiesta, o un insieme di campi, più grande di quanto desideri elaborare MUST rispondere con un appropriato codice di stato 4xx (Client Error). Ignorare tali campi di intestazione aumenterebbe la vulnerabilità del server agli attacchi di request smuggling (Sezione 9.5).

Un client MAY scartare o troncare i campi di intestazione ricevuti che sono più grandi di quanto il client desideri elaborare, se la semantica del campo è tale che i valori scartati possono essere ignorati in modo sicuro senza modificare l'inquadratura del messaggio o la semantica della risposta.

3.2.6. Componenti dei valori di campo​

La maggior parte dei valori dei campi di intestazione HTTP è definita usando componenti sintattici comuni (token, quoted-string e comment) separati da spazi bianchi o da specifici caratteri delimitatori. I delimitatori sono scelti dall'insieme dei caratteri visivi US-ASCII non consentiti in un token (DQUOTE e "(),/:;<=>?@[]{}").

token          = 1*tchar

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

Una stringa di testo viene analizzata come valore singolo se è racchiusa tra virgolette doppie.

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

I commenti possono essere inclusi in alcuni campi di intestazione HTTP racchiudendo il testo del commento tra parentesi. I commenti sono consentiti solo nei campi che contengono "comment" come parte della loro definizione di valore di campo.

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

L'ottetto barra rovesciata ("") può essere usato come meccanismo di quoting a singolo ottetto all'interno dei costrutti quoted-string e comment. I destinatari che elaborano il valore di una quoted-string MUST gestire un quoted-pair come se fosse sostituito dall'ottetto che segue la barra rovesciata.

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

Un mittente SHOULD NOT generare un quoted-pair in una quoted-string, se non dove è necessario per citare gli ottetti DQUOTE e barra rovesciata che compaiono all'interno di quella stringa. Un mittente SHOULD NOT generare un quoted-pair in un commento, se non dove è necessario per citare le parentesi ["(" e ")"] e gli ottetti barra rovesciata che compaiono all'interno di quel commento.

3.3. Corpo del messaggio​

Il corpo del messaggio (se presente) di un messaggio HTTP è usato per trasportare il payload del corpo di quella richiesta o risposta. Il corpo del messaggio è identico al payload del corpo, a meno che non sia stata applicata una transfer coding, come descritto nella Sezione 3.3.1.

message-body = *OCTET

Le regole che stabiliscono quando è consentito un corpo del messaggio in un messaggio differiscono tra richieste e risposte.

La presenza di un corpo del messaggio in una richiesta è segnalata da un campo di intestazione Content-Length o Transfer-Encoding. L'inquadratura del messaggio di richiesta è indipendente dalla semantica del metodo, anche se il metodo non definisce alcun uso per un corpo del messaggio.

La presenza di un corpo del messaggio in una risposta dipende sia dal metodo di richiesta a cui la risposta risponde sia dal codice di stato della risposta (Sezione 3.1.2). Le risposte al metodo di richiesta HEAD (Sezione 4.3.2 di [RFC7231]) non includono mai un corpo del messaggio, perché i campi di intestazione della risposta associati (ad es. Transfer-Encoding, Content-Length, ecc.), se presenti, indicano solo quali sarebbero stati i loro valori se il metodo di richiesta fosse stato GET (Sezione 4.3.1 di [RFC7231]). Le risposte 2xx (Successful) a un metodo di richiesta CONNECT (Sezione 4.3.6 di [RFC7231]) passano invece alla modalità tunnel anziché avere un corpo del messaggio. Tutte le risposte 1xx (Informational), 204 (No Content) e 304 (Not Modified) non includono un corpo del messaggio. Tutte le altre risposte includono un corpo del messaggio, sebbene il corpo possa essere di lunghezza zero.

3.3.1. Transfer-Encoding​

Il campo di intestazione Transfer-Encoding elenca i nomi delle transfer coding corrispondenti alla sequenza di transfer coding che sono state (o saranno) applicate al payload del corpo per formare il corpo del messaggio. Le transfer coding sono definite nella Sezione 4.

Transfer-Encoding = 1#transfer-coding

Transfer-Encoding è analogo al campo Content-Transfer-Encoding di MIME, che era stato progettato per consentire il trasporto sicuro di dati binari su un servizio di trasporto a 7 bit ([RFC2045], Sezione 6). Tuttavia, il trasporto sicuro ha un obiettivo diverso per un protocollo di trasferimento 8bit-clean. Nel caso di HTTP, Transfer-Encoding è principalmente destinato a delimitare con precisione un payload generato dinamicamente e a distinguere le codifiche del payload applicate solo per efficienza di trasporto o sicurezza da quelle che sono caratteristiche della risorsa selezionata.

Un destinatario MUST essere in grado di analizzare la chunked transfer coding (Sezione 4.1), perché svolge un ruolo cruciale nell'inquadrare i messaggi quando la dimensione del payload del corpo non è nota in anticipo. Un mittente MUST NOT applicare chunked più di una volta a un corpo del messaggio (cioè non è consentito suddividere in chunk un messaggio già suddiviso in chunk). Se al payload del corpo di una richiesta viene applicata una transfer coding diversa da chunked, il mittente MUST applicare chunked come transfer coding finale per garantire che il messaggio sia inquadrato correttamente. Se al payload del corpo di una risposta viene applicata una transfer coding diversa da chunked, il mittente MUST o applicare chunked come transfer coding finale oppure terminare il messaggio chiudendo la connessione.

Ad esempio,

Transfer-Encoding: gzip, chunked

indica che il payload del corpo è stato compresso usando la codifica gzip e poi suddiviso in chunk usando la codifica chunked durante la formazione del corpo del messaggio.

A differenza di Content-Encoding (Sezione 3.1.2.1 di [RFC7231]), Transfer-Encoding è una proprietà del messaggio, non della rappresentazione, e qualsiasi destinatario lungo la catena richiesta/risposta MAY decodificare le transfer coding ricevute o applicare transfer coding aggiuntive al corpo del messaggio, supponendo che siano apportate le corrispondenti modifiche al field-value di Transfer-Encoding. Informazioni aggiuntive sui parametri di codifica possono essere fornite da altri campi di intestazione non definiti da questa specifica.

Transfer-Encoding MAY essere inviato in una risposta a una richiesta HEAD o in una risposta 304 (Not Modified) (Sezione 4.1 di [RFC7232]) a una richiesta GET, nessuna delle quali include un corpo del messaggio, per indicare che l'origin server avrebbe applicato una transfer coding al corpo del messaggio se la richiesta fosse stata un GET incondizionato. Questa indicazione non è tuttavia necessaria, perché qualsiasi destinatario sulla catena di risposta (incluso l'origin server) può rimuovere le transfer coding quando non sono necessarie.

Un server MUST NOT inviare un campo di intestazione Transfer-Encoding in alcuna risposta con un codice di stato 1xx (Informational) o 204 (No Content). Un server MUST NOT inviare un campo di intestazione Transfer-Encoding in alcuna risposta 2xx (Successful) a una richiesta CONNECT (Sezione 4.3.6 di [RFC7231]).

Transfer-Encoding è stato aggiunto in HTTP/1.1. Si presume generalmente che le implementazioni che dichiarano solo il supporto di HTTP/1.0 non comprenderanno come elaborare un payload con codifica di trasferimento. Un client MUST NOT inviare una richiesta contenente Transfer-Encoding a meno che non sappia che il server gestirà richieste HTTP/1.1 (o successive); tale conoscenza può assumere la forma di una specifica configurazione utente oppure derivare dal ricordo della versione di una risposta ricevuta in precedenza. Un server MUST NOT inviare una risposta contenente Transfer-Encoding a meno che la richiesta corrispondente non indichi HTTP/1.1 (o successivo).

Un server che riceve un messaggio di richiesta con una transfer coding che non comprende SHOULD rispondere con 501 (Not Implemented).

3.3.2. Content-Length​

Quando un messaggio non ha un campo di intestazione Transfer-Encoding, un campo di intestazione Content-Length può fornire la dimensione prevista, come numero decimale di ottetti, per un potenziale payload del corpo. Per i messaggi che includono un payload del corpo, il field-value di Content-Length fornisce le informazioni di inquadratura necessarie per determinare dove termina il corpo (e il messaggio). Per i messaggi che non includono un payload del corpo, Content-Length indica la dimensione della rappresentazione selezionata (Sezione 3 di [RFC7231]).

Content-Length = 1*DIGIT

Un esempio è

Content-Length: 3495

Un mittente MUST NOT inviare un campo di intestazione Content-Length in alcun messaggio che contenga un campo di intestazione Transfer-Encoding.

Uno user agent SHOULD inviare un Content-Length in un messaggio di richiesta quando non viene inviato alcun Transfer-Encoding e il metodo di richiesta definisce un significato per un payload del corpo racchiuso. Ad esempio, un campo di intestazione Content-Length viene normalmente inviato in una richiesta POST anche quando il valore è 0 (che indica un payload del corpo vuoto). Uno user agent SHOULD NOT inviare un campo di intestazione Content-Length quando il messaggio di richiesta non contiene un payload del corpo e la semantica del metodo non prevede tale corpo.

Un server MAY inviare un campo di intestazione Content-Length in una risposta a una richiesta HEAD (Sezione 4.3.2 di [RFC7231]); un server MUST NOT inviare Content-Length in tale risposta a meno che il suo field-value non sia uguale al numero decimale di ottetti che sarebbero stati inviati nel payload del corpo di una risposta se la stessa richiesta avesse usato il metodo GET.

Un server MAY inviare un campo di intestazione Content-Length in una risposta 304 (Not Modified) a una richiesta GET condizionale (Sezione 4.1 di [RFC7232]); un server MUST NOT inviare Content-Length in tale risposta a meno che il suo field-value non sia uguale al numero decimale di ottetti che sarebbero stati inviati nel payload del corpo di una risposta 200 (OK) alla stessa richiesta.

Un server MUST NOT inviare un campo di intestazione Content-Length in alcuna risposta con un codice di stato 1xx (Informational) o 204 (No Content). Un server MUST NOT inviare un campo di intestazione Content-Length in alcuna risposta 2xx (Successful) a una richiesta CONNECT (Sezione 4.3.6 di [RFC7231]).

A parte i casi definiti sopra, in assenza di Transfer-Encoding, un origin server SHOULD inviare un campo di intestazione Content-Length quando la dimensione del payload del corpo è nota prima dell'invio dell'intera sezione di intestazione. Ciò consentirà ai destinatari a valle di misurare l'avanzamento del trasferimento, di sapere quando un messaggio ricevuto è completo e di riutilizzare potenzialmente la connessione per richieste aggiuntive.

Qualsiasi valore di campo Content-Length maggiore o uguale a zero è valido. Poiché non esiste un limite predefinito alla lunghezza di un payload, un destinatario MUST prevedere numeri decimali potenzialmente grandi e prevenire errori di analisi dovuti a overflow nelle conversioni intere (Sezione 9.3).

Se viene ricevuto un messaggio che presenta più campi di intestazione Content-Length con field-value costituiti dallo stesso valore decimale, oppure un unico campo di intestazione Content-Length con un valore di campo contenente un elenco di valori decimali identici (ad es. "Content-Length: 42, 42"), il che indica che campi di intestazione Content-Length duplicati sono stati generati o combinati da un processore di messaggi a monte, allora il destinatario MUST o rifiutare il messaggio come non valido, oppure sostituire i field-value duplicati con un unico campo Content-Length valido contenente quel valore decimale, prima di determinare la lunghezza del corpo del messaggio o di inoltrare il messaggio.

Nota: l'uso di Content-Length da parte di HTTP per l'inquadratura dei messaggi differisce in modo significativo dall'uso dello stesso campo in MIME, dove è un campo opzionale usato solo all'interno del media type "message/external-body".

3.3.3. Lunghezza del corpo del messaggio​

La lunghezza di un corpo del messaggio è determinata da una delle seguenti modalità (in ordine di precedenza):

  1. Qualsiasi risposta a una richiesta HEAD e qualsiasi risposta con un codice di stato 1xx (Informational), 204 (No Content) o 304 (Not Modified) è sempre terminata dalla prima riga vuota dopo i campi di intestazione, indipendentemente dai campi di intestazione presenti nel messaggio, e pertanto non può contenere un corpo del messaggio.

  2. Qualsiasi risposta 2xx (Successful) a una richiesta CONNECT implica che la connessione diventerà un tunnel immediatamente dopo la riga vuota che conclude i campi di intestazione. Un client MUST ignorare qualsiasi campo di intestazione Content-Length o Transfer-Encoding ricevuto in tale messaggio.

  3. Se è presente un campo di intestazione Transfer-Encoding e la chunked transfer coding (Sezione 4.1) è la codifica finale, la lunghezza del corpo del messaggio è determinata leggendo e decodificando i dati suddivisi in chunk finché la transfer coding non indica che i dati sono completi.

Se in una risposta è presente un campo di intestazione Transfer-Encoding e la chunked transfer coding non è la codifica finale, la lunghezza del corpo del messaggio è determinata leggendo dalla connessione finché questa non viene chiusa dal server. Se in una richiesta è presente un campo di intestazione Transfer-Encoding e la chunked transfer coding non è la codifica finale, la lunghezza del corpo del messaggio non può essere determinata in modo affidabile; il server MUST rispondere con il codice di stato 400 (Bad Request) e poi chiudere la connessione.

Se viene ricevuto un messaggio con sia un campo di intestazione Transfer-Encoding sia uno Content-Length, Transfer-Encoding prevale su Content-Length. Tale messaggio potrebbe indicare un tentativo di effettuare un request smuggling (Sezione 9.5) o un response splitting (Sezione 9.4) e dovrebbe essere gestito come errore. Un mittente MUST rimuovere il campo Content-Length ricevuto prima di inoltrare tale messaggio a valle.

  1. Se viene ricevuto un messaggio senza Transfer-Encoding e con più campi di intestazione Content-Length che hanno field-value diversi oppure con un unico campo di intestazione Content-Length che ha un valore non valido, allora l'inquadratura del messaggio non è valida e il destinatario MUST trattarla come un errore non recuperabile. Se si tratta di un messaggio di richiesta, il server MUST rispondere con un codice di stato 400 (Bad Request) e poi chiudere la connessione. Se si tratta di un messaggio di risposta ricevuto da un proxy, il proxy MUST chiudere la connessione al server, scartare la risposta ricevuta e inviare al client una risposta 502 (Bad Gateway). Se si tratta di un messaggio di risposta ricevuto da uno user agent, lo user agent MUST chiudere la connessione al server e scartare la risposta ricevuta.

  2. Se è presente un campo di intestazione Content-Length valido senza Transfer-Encoding, il suo valore decimale definisce la lunghezza prevista del corpo del messaggio in ottetti. Se il mittente chiude la connessione o il destinatario va in timeout prima che venga ricevuto il numero di ottetti indicato, il destinatario MUST considerare il messaggio incompleto e chiudere la connessione.

  3. Se si tratta di un messaggio di richiesta e nessuno dei casi precedenti è vero, allora la lunghezza del corpo del messaggio è zero (non è presente alcun corpo del messaggio).

  4. In caso contrario, si tratta di un messaggio di risposta senza una lunghezza del corpo del messaggio dichiarata, quindi la lunghezza del corpo del messaggio è determinata dal numero di ottetti ricevuti prima che il server chiuda la connessione.

Poiché non c'è modo di distinguere un messaggio completato con successo e delimitato dalla chiusura da un messaggio ricevuto parzialmente e interrotto da un guasto di rete, un server SHOULD generare messaggi con codifica o delimitati da lunghezza ove possibile. La funzionalità di delimitazione tramite chiusura esiste principalmente per la retrocompatibilità con HTTP/1.0.

Un server MAY rifiutare una richiesta che contiene un corpo del messaggio ma non un Content-Length rispondendo con 411 (Length Required).

A meno che non sia stata applicata una transfer coding diversa da chunked, un client che invia una richiesta contenente un corpo del messaggio SHOULD usare un campo di intestazione Content-Length valido se la lunghezza del corpo del messaggio è nota in anticipo, anziché la chunked transfer coding, poiché alcuni servizi esistenti rispondono alla chunked con un codice di stato 411 (Length Required) anche se comprendono la chunked transfer coding. Ciò avviene tipicamente perché tali servizi sono implementati tramite un gateway che richiede un content-length prima di essere chiamato e il server non è in grado o non vuole memorizzare nel buffer l'intera richiesta prima dell'elaborazione.

Uno user agent che invia una richiesta contenente un corpo del messaggio MUST inviare un campo di intestazione Content-Length valido se non sa che il server gestirà richieste HTTP/1.1 (o successive); tale conoscenza può assumere la forma di una specifica configurazione utente oppure derivare dal ricordo della versione di una risposta ricevuta in precedenza.

Se la risposta finale all'ultima richiesta su una connessione è stata completamente ricevuta e rimangono dati aggiuntivi da leggere, uno user agent MAY scartare i dati rimanenti o tentare di determinare se tali dati appartengono al corpo della risposta precedente, il che potrebbe essere il caso se il valore Content-Length del messaggio precedente è errato. Un client MUST NOT elaborare, memorizzare in cache o inoltrare tali dati extra come risposta separata, poiché un tale comportamento sarebbe vulnerabile al cache poisoning.

3.4. Gestione dei messaggi incompleti​

Un server che riceve un messaggio di richiesta incompleto, di solito a causa di una richiesta annullata o di un'eccezione di timeout attivata, MAY inviare una risposta di errore prima di chiudere la connessione.

Un client che riceve un messaggio di risposta incompleto, cosa che può verificarsi quando una connessione viene chiusa prematuramente o quando la decodifica di una presunta chunked transfer coding fallisce, MUST registrare il messaggio come incompleto. I requisiti di cache per le risposte incomplete sono definiti nella Sezione 3 di [RFC7234].

Se una risposta termina nel mezzo della sezione di intestazione (prima che venga ricevuta la riga vuota) e il codice di stato potrebbe basarsi sui campi di intestazione per veicolare il significato completo della risposta, allora il client non può presumere che tale significato sia stato veicolato; il client potrebbe dover ripetere la richiesta per determinare quale azione intraprendere successivamente.

Un corpo del messaggio che usa la chunked transfer coding è incompleto se non è stato ricevuto il chunk di dimensione zero che termina la codifica. Un messaggio che usa un Content-Length valido è incompleto se la dimensione del corpo del messaggio ricevuto (in ottetti) è inferiore al valore indicato da Content-Length. Una risposta che non ha né chunked transfer coding né Content-Length è terminata dalla chiusura della connessione e, pertanto, è considerata completa indipendentemente dal numero di ottetti del corpo del messaggio ricevuti, purché la sezione di intestazione sia stata ricevuta intatta.

3.5. Robustezza dell'analisi dei messaggi​

Le vecchie implementazioni di user agent HTTP/1.0 potrebbero inviare un CRLF aggiuntivo dopo una richiesta POST come soluzione alternativa per alcune prime applicazioni server che non riuscivano a leggere il contenuto del corpo del messaggio non terminato da un fine riga. Uno user agent HTTP/1.1 MUST NOT anteporre o far seguire a una richiesta un CRLF aggiuntivo. Se si desidera terminare il corpo del messaggio di richiesta con un fine riga, allora lo user agent MUST conteggiare gli ottetti CRLF di terminazione come parte della lunghezza del corpo del messaggio.

A fini di robustezza, un server che si aspetta di ricevere e analizzare una request-line SHOULD ignorare almeno una riga vuota (CRLF) ricevuta prima della request-line.

Sebbene il terminatore di riga per la start-line e i campi di intestazione sia la sequenza CRLF, un destinatario MAY riconoscere un singolo LF come terminatore di riga e ignorare qualsiasi CR che lo precede.

Sebbene le regole grammaticali della request-line e della status-line richiedano che ciascuno degli elementi componenti sia separato da un singolo ottetto SP, i destinatari MAY invece analizzare su confini di parola delimitati da spazi bianchi e, a parte il terminatore CRLF, trattare qualsiasi forma di spazio bianco come separatore SP, ignorando gli spazi bianchi iniziali o finali; tali spazi bianchi includono uno o più dei seguenti ottetti: SP, HTAB, VT (%x0B), FF (%x0C) o CR nudo. Tuttavia, un'analisi indulgente può comportare vulnerabilità di sicurezza se vi sono più destinatari del messaggio e ciascuno ha la propria interpretazione unica della robustezza (vedere la Sezione 9.5).

Quando un server in ascolto solo di messaggi di richiesta HTTP, o che elabora ciò che dalla start-line appare essere un messaggio di richiesta HTTP, riceve una sequenza di ottetti che non corrisponde alla grammatica HTTP-message a parte le eccezioni di robustezza elencate sopra, il server SHOULD rispondere con una risposta 400 (Bad Request).