Passa al contenuto principale

6. Astrazione dei Messaggi (Message Abstraction)

Ogni versione principale di HTTP definisce la propria sintassi per comunicare i messaggi. Questa sezione definisce un tipo di dati astratto per i messaggi HTTP basato su una generalizzazione di queste caratteristiche dei messaggi, struttura comune e capacità di trasmettere semantica. Questa astrazione viene utilizzata per definire requisiti su mittenti e destinatari indipendenti dalla versione HTTP, in modo che un messaggio in una versione possa essere ritrasmesso attraverso altre versioni senza cambiarne il significato.

Un "messaggio" (message) è composto dai seguenti elementi:

  • dati di controllo per descrivere e instradare il messaggio,

  • una tabella di ricerca degli header di coppie nome/valore per estendere tali dati di controllo e trasmettere informazioni aggiuntive sul mittente, messaggio, contenuto o contesto,

  • un flusso di contenuto potenzialmente illimitato, e

  • una tabella di ricerca dei trailer di coppie nome/valore per comunicare informazioni ottenute durante l'invio del contenuto.

Il framing e i dati di controllo vengono inviati per primi, seguiti da una sezione di header contenente campi per la tabella degli header. Quando un messaggio include contenuto, il contenuto viene inviato dopo la sezione di header, potenzialmente seguito da una sezione di trailer che potrebbe contenere campi per la tabella dei trailer.

I messaggi devono essere elaborati come un flusso, in cui lo scopo di quel flusso e la sua elaborazione continuata vengono rivelati durante la lettura. Quindi, i dati di controllo descrivono ciò che il destinatario deve sapere immediatamente, i campi di header descrivono ciò che deve essere conosciuto prima di ricevere il contenuto, il contenuto (quando presente) presumibilmente contiene ciò che il destinatario desidera o necessita per soddisfare la semantica del messaggio, e i campi di trailer forniscono metadati opzionali che erano sconosciuti prima di inviare il contenuto.

I messaggi sono intesi come "auto-descrittivi" (self-descriptive): tutto ciò che un destinatario deve sapere sul messaggio può essere determinato osservando il messaggio stesso, dopo aver decodificato o ricostituito le parti che sono state compresse o elise durante il transito, senza richiedere una comprensione dello stato corrente dell'applicazione del mittente (stabilito tramite messaggi precedenti). Tuttavia, un client DEVE (MUST) mantenere la conoscenza della richiesta durante l'analisi, l'interpretazione o la memorizzazione nella cache di una risposta corrispondente. Ad esempio, le risposte al metodo HEAD appaiono proprio come l'inizio di una risposta a GET ma non possono essere analizzate allo stesso modo.

Si noti che questa astrazione di messaggio è una generalizzazione su molte versioni di HTTP, incluse funzionalità che potrebbero non essere presenti in alcune versioni. Ad esempio, i trailer sono stati introdotti all'interno della codifica di trasferimento chunked HTTP/1.1 come sezione di trailer dopo il contenuto. Una funzionalità equivalente è presente in HTTP/2 e HTTP/3 all'interno del blocco di header che termina ogni flusso.

6.1. Framing e Completezza (Framing and Completeness)

Il framing dei messaggi (Message framing) indica come ogni messaggio inizia e termina, in modo che ogni messaggio possa essere distinto da altri messaggi o rumore sulla stessa connessione. Ogni versione principale di HTTP definisce il proprio meccanismo di framing.

HTTP/0.9 e le prime implementazioni di HTTP/1.0 utilizzavano la chiusura della connessione sottostante per terminare una risposta. Per compatibilità con le versioni precedenti, questo framing implicito è consentito anche in HTTP/1.1. Tuttavia, il framing implicito può non riuscire a distinguere una risposta incompleta se la connessione si chiude prematuramente. Per questo motivo, quasi tutte le implementazioni moderne utilizzano il framing esplicito sotto forma di sequenze di dati di messaggio delimitate dalla lunghezza.

Un messaggio è considerato "completo" (complete) quando tutti gli ottetti indicati dal suo framing sono disponibili. Si noti che, quando non viene utilizzato alcun framing esplicito, un messaggio di risposta che termina con la chiusura della connessione sottostante è considerato completo anche se potrebbe essere indistinguibile da una risposta incompleta, a meno che un errore a livello di trasporto non indichi che non è completo.

6.2. Dati di Controllo (Control Data)

I messaggi iniziano con dati di controllo che descrivono il loro scopo principale. I dati di controllo del messaggio di richiesta includono un metodo di richiesta (request method) (Sezione 9), un target di richiesta (request target) (Sezione 7.1) e una versione del protocollo (protocol version) (Sezione 2.5). I dati di controllo del messaggio di risposta includono un codice di stato (status code) (Sezione 15), una frase di ragione (reason phrase) opzionale e una versione del protocollo.

In HTTP/1.1 ([HTTP/1.1]) e versioni precedenti, i dati di controllo vengono inviati come prima riga di un messaggio. In HTTP/2 ([HTTP/2]) e HTTP/3 ([HTTP/3]), i dati di controllo vengono inviati come campi pseudo-header con un prefisso di nome riservato (ad es., ":authority").

Ogni messaggio HTTP ha una versione del protocollo. A seconda della versione in uso, potrebbe essere identificata esplicitamente all'interno del messaggio o dedotta dalla connessione su cui viene ricevuto il messaggio. I destinatari utilizzano tali informazioni sulla versione per determinare limitazioni o potenziale per comunicazioni successive con quel mittente.

Quando un messaggio viene inoltrato da un intermediario, la versione del protocollo viene aggiornata per riflettere la versione utilizzata da tale intermediario. Il campo di header Via (Sezione 7.6.3) viene utilizzato per comunicare informazioni sul protocollo upstream all'interno di un messaggio inoltrato.

Un client DOVREBBE (SHOULD) inviare una versione di richiesta uguale alla versione più alta a cui il client è conforme e la cui versione principale non è superiore alla versione più alta supportata dal server, se nota. Un client NON DEVE (MUST NOT) inviare una versione a cui non è conforme.

Un client PUÒ (MAY) inviare una versione di richiesta inferiore se è noto che il server implementa in modo errato la specifica HTTP, ma solo dopo che il client ha tentato almeno una richiesta normale e ha determinato dal codice di stato di risposta o dai campi di header (ad es., Server) che il server gestisce in modo improprio versioni di richiesta superiori.

Un server DOVREBBE (SHOULD) inviare una versione di risposta uguale alla versione più alta a cui il server è conforme e che ha una versione principale inferiore o uguale a quella ricevuta nella richiesta. Un server NON DEVE (MUST NOT) inviare una versione a cui non è conforme. Un server può inviare una risposta 505 (HTTP Version Not Supported) se desidera, per qualsiasi motivo, rifiutare il servizio della versione principale del protocollo del client.

Un destinatario che riceve un messaggio con un numero di versione principale che implementa e un numero di versione minore superiore a quello che implementa DOVREBBE (SHOULD) elaborare il messaggio come se fosse nella versione minore più alta all'interno di quella versione principale a cui il destinatario è conforme. Un destinatario può presumere che un messaggio con una versione minore superiore, quando inviato a un destinatario che non ha ancora indicato il supporto per quella versione superiore, sia sufficientemente retrocompatibile da essere elaborato in sicurezza da qualsiasi implementazione della stessa versione principale.

6.3. Campi di Header (Header Fields)

I campi (Sezione 5) che vengono inviati o ricevuti prima del contenuto sono chiamati "campi di header" (header fields) (o semplicemente "header" colloquialmente).

La "sezione di header" (header section) di un messaggio è costituita da una sequenza di righe di campo di header. Ogni campo di header potrebbe modificare o estendere la semantica del messaggio, descrivere il mittente, definire il contenuto o fornire contesto aggiuntivo.

Nota: Ci riferiamo ai campi nominati specificamente come "campo di header" quando sono consentiti solo per essere inviati nella sezione di header.

6.4. Contenuto (Content)

I messaggi HTTP spesso trasferiscono una rappresentazione completa o parziale come "contenuto" (content) del messaggio: un flusso di ottetti inviato dopo la sezione di header, come delimitato dal framing del messaggio.

Questa definizione astratta di contenuto riflette i dati dopo che sono stati estratti dal framing del messaggio. Ad esempio, un corpo di messaggio HTTP/1.1 (Sezione 6 di [HTTP/1.1]) potrebbe consistere in un flusso di dati codificato con la codifica di trasferimento chunked -- una sequenza di blocchi di dati, un blocco di lunghezza zero e una sezione di trailer -- mentre il contenuto di quello stesso messaggio include solo il flusso di dati dopo che la codifica di trasferimento è stata decodificata; non include le lunghezze dei blocchi, la sintassi di framing chunked, né i campi di trailer (Sezione 6.5).

Nota: Alcuni nomi di campo hanno un prefisso "Content-". Questa è una convenzione informale; mentre alcuni di questi campi si riferiscono al contenuto del messaggio, come definito sopra, altri sono limitati alla rappresentazione selezionata (Sezione 3.2). Consultare la definizione del singolo campo per disambiguare.

6.4.1. Semantica del Contenuto (Content Semantics)

Lo scopo del contenuto in una richiesta è definito dalla semantica del metodo (Sezione 9).

Ad esempio, una rappresentazione nel contenuto di una richiesta PUT (Sezione 9.3.4) rappresenta lo stato desiderato della risorsa di destinazione dopo che la richiesta è stata applicata con successo, mentre una rappresentazione nel contenuto di una richiesta POST (Sezione 9.3.3) rappresenta informazioni da elaborare dalla risorsa di destinazione.

In una risposta, lo scopo del contenuto è definito dal metodo di richiesta, dal codice di stato della risposta (Sezione 15) e dai campi di risposta che descrivono tale contenuto. Ad esempio, il contenuto di una risposta 200 (OK) a GET (Sezione 9.3.1) rappresenta lo stato corrente della risorsa di destinazione, come osservato al momento della data di origine del messaggio (Sezione 6.6.1), mentre il contenuto dello stesso codice di stato in una risposta a POST potrebbe rappresentare sia il risultato dell'elaborazione sia il nuovo stato della risorsa di destinazione dopo l'applicazione dell'elaborazione.

Il contenuto di una risposta 206 (Partial Content) a GET contiene una singola parte della rappresentazione selezionata o un corpo di messaggio multipart contenente più parti di quella rappresentazione, come descritto nella Sezione 15.3.7.

I messaggi di risposta con un codice di stato di errore di solito contengono contenuto che rappresenta la condizione di errore, in modo che il contenuto descriva lo stato di errore e quali passaggi sono suggeriti per risolverlo.

Le risposte al metodo di richiesta HEAD (Sezione 9.3.2) non includono mai contenuto; i campi di header di risposta associati indicano solo quali sarebbero stati i loro valori se il metodo di richiesta fosse stato GET (Sezione 9.3.1).

Le risposte 2xx (Successful) a un metodo di richiesta CONNECT (Sezione 9.3.6) commutano la connessione in modalità tunnel invece di avere contenuto.

Tutte le risposte 1xx (Informational), 204 (No Content) e 304 (Not Modified) non includono contenuto.

Tutte le altre risposte includono contenuto, sebbene tale contenuto potrebbe essere di lunghezza zero.

6.4.2. Identificazione del Contenuto (Identifying Content)

Quando una rappresentazione completa o parziale viene trasferita come contenuto del messaggio, è spesso desiderabile che il mittente fornisca, o che il destinatario determini, un identificatore per una risorsa corrispondente a quella rappresentazione specifica. Ad esempio, un client che effettua una richiesta GET su una risorsa per "il rapporto meteorologico corrente" potrebbe desiderare un identificatore specifico per il contenuto restituito (ad es., "rapporto meteorologico per Laguna Beach il 20210720T1711"). Questo può essere utile per condividere o aggiungere ai segnalibri contenuto da risorse che si prevede abbiano rappresentazioni mutevoli nel tempo.

Per un messaggio di richiesta:

  • Se la richiesta ha un campo di header Content-Location, allora il mittente afferma che il contenuto è una rappresentazione della risorsa identificata dal valore del campo Content-Location. Tuttavia, tale affermazione non può essere considerata attendibile a meno che non possa essere verificata con altri mezzi (non definiti da questa specifica). Le informazioni potrebbero comunque essere utili per i collegamenti alla cronologia delle revisioni.

  • Altrimenti, il contenuto non è identificato da HTTP, ma un identificatore più specifico potrebbe essere fornito all'interno del contenuto stesso.

Per un messaggio di risposta, le seguenti regole vengono applicate in ordine fino a quando non viene trovata una corrispondenza:

  1. Se il metodo di richiesta è HEAD o il codice di stato della risposta è 204 (No Content) o 304 (Not Modified), non c'è contenuto nella risposta.

  2. Se il metodo di richiesta è GET e il codice di stato della risposta è 200 (OK), il contenuto è una rappresentazione della risorsa di destinazione (Sezione 7.1).

  3. Se il metodo di richiesta è GET e il codice di stato della risposta è 203 (Non-Authoritative Information), il contenuto è una rappresentazione potenzialmente modificata o migliorata della risorsa di destinazione come fornita da un intermediario.

  4. Se il metodo di richiesta è GET e il codice di stato della risposta è 206 (Partial Content), il contenuto è una o più parti di una rappresentazione della risorsa di destinazione.

  5. Se la risposta ha un campo di header Content-Location e il suo valore di campo è un riferimento allo stesso URI dell'URI di destinazione, il contenuto è una rappresentazione della risorsa di destinazione.

  6. Se la risposta ha un campo di header Content-Location e il suo valore di campo è un riferimento a un URI diverso dall'URI di destinazione, allora il mittente afferma che il contenuto è una rappresentazione della risorsa identificata dal valore del campo Content-Location. Tuttavia, tale affermazione non può essere considerata attendibile a meno che non possa essere verificata con altri mezzi (non definiti da questa specifica).

  7. Altrimenti, il contenuto non è identificato da HTTP, ma un identificatore più specifico potrebbe essere fornito all'interno del contenuto stesso.

6.5. Campi di Trailer (Trailer Fields)

I campi (Sezione 5) che si trovano all'interno di una "sezione di trailer" (trailer section) sono chiamati "campi di trailer" (trailer fields) (o semplicemente "trailer" colloquialmente). I campi di trailer possono essere utili per fornire controlli di integrità dei messaggi, firme digitali, metriche di consegna o informazioni sullo stato della post-elaborazione.

I campi di trailer dovrebbero essere elaborati e memorizzati separatamente dai campi nella sezione di header per evitare di contraddire la semantica del messaggio nota al momento in cui la sezione di header era completa. La presenza o l'assenza di determinati campi di header potrebbe influenzare le scelte fatte per l'instradamento o l'elaborazione del messaggio nel suo insieme prima che i trailer vengano ricevuti; tali scelte non possono essere annullate dalla successiva scoperta di campi di trailer.

6.5.1. Limitazioni sull'Uso dei Trailer (Limitations on Use of Trailers)

Una sezione di trailer è possibile solo quando supportata dalla versione di HTTP in uso e abilitata da un meccanismo di framing esplicito. Ad esempio, la codifica di trasferimento chunked in HTTP/1.1 consente di inviare una sezione di trailer dopo il contenuto (Sezione 7.1.2 di [HTTP/1.1]).

Molti campi non possono essere elaborati al di fuori della sezione di header perché la loro valutazione è necessaria prima di ricevere il contenuto, come quelli che descrivono il framing del messaggio, l'instradamento, l'autenticazione, i modificatori di richiesta, i controlli di risposta o il formato del contenuto. Un mittente NON DEVE (MUST NOT) generare un campo di trailer a meno che il mittente non sappia che la definizione del nome del campo di header corrispondente consente l'invio del campo nei trailer.

I campi di trailer possono essere difficili da elaborare per gli intermediari che inoltrano messaggi da una versione di protocollo a un'altra. Se l'intero messaggio può essere memorizzato nel buffer durante il transito, alcuni intermediari potrebbero unire i campi di trailer nella sezione di header (come appropriato) prima che venga inoltrato. Tuttavia, nella maggior parte dei casi, i trailer vengono semplicemente scartati. Un destinatario NON DEVE (MUST NOT) unire un campo di trailer in una sezione di header a meno che il destinatario non comprenda la definizione del campo di header corrispondente e tale definizione non consenta esplicitamente e definisca come i valori del campo di trailer possano essere uniti in sicurezza.

La presenza della parola chiave "trailers" nel campo di header TE (Sezione 10.1.4) di una richiesta indica che il client è disposto ad accettare campi di trailer, per conto di se stesso e di eventuali client downstream. Per le richieste da un intermediario, ciò implica che tutti i client downstream sono disposti ad accettare campi di trailer nella risposta inoltrata. Si noti che la presenza di "trailers" non significa che il/i client elaborerà/elaboreranno alcun particolare campo di trailer nella risposta; solo che la/le sezione/i di trailer non verrà/verranno eliminata/e da nessuno dei client.

A causa del potenziale di scarto dei campi di trailer durante il transito, un server NON DOVREBBE (SHOULD NOT) generare campi di trailer che ritiene necessari per l'agente utente da ricevere.

6.5.2. Elaborazione dei Campi di Trailer (Processing Trailer Fields)

Il campo di header "Trailer" (Sezione 6.6.2) può essere inviato per indicare i campi che probabilmente verranno inviati nella sezione di trailer, il che consente ai destinatari di prepararsi per la loro ricezione prima di elaborare il contenuto. Ad esempio, ciò potrebbe essere utile se un nome di campo indica che un checksum dinamico dovrebbe essere calcolato mentre il contenuto viene ricevuto e quindi immediatamente verificato al ricevimento del valore del campo di trailer.

Come i campi di header, i campi di trailer con lo stesso nome vengono elaborati nell'ordine ricevuto; più righe di campo di trailer con lo stesso nome hanno la semantica equivalente all'aggiunta dei valori multipli come elenco di membri. I campi di trailer che potrebbero essere generati più di una volta durante un messaggio DEVONO (MUST) essere definiti come campo basato su elenco anche se ogni valore membro viene elaborato solo una volta per riga di campo ricevuta.

Alla fine di un messaggio, un destinatario PUÒ (MAY) trattare l'insieme dei campi di trailer ricevuti come una struttura dati di coppie nome/valore, simile (ma separata) ai campi di header. Aspettative di elaborazione aggiuntive, se presenti, possono essere definite all'interno della specifica del campo per un campo destinato all'uso nei trailer.

6.6. Metadati del Messaggio (Message Metadata)

I campi che descrivono il messaggio stesso, come quando e come il messaggio è stato generato, possono apparire sia nelle richieste che nelle risposte.

6.6.1. Date

Il campo di header "Date" rappresenta la data e l'ora in cui il messaggio è stato originato, avendo la stessa semantica del campo Origination Date Field (orig-date) definito nella Sezione 3.6.1 di [RFC5322]. Il valore del campo è un HTTP-date, come definito nella Sezione 5.6.7.

Date = HTTP-date

Un esempio è:

Date: Tue, 15 Nov 1994 08:12:31 GMT

Un mittente che genera un campo di header Date DOVREBBE (SHOULD) generare il suo valore di campo come la migliore approssimazione disponibile della data e dell'ora di generazione del messaggio. In teoria, la data dovrebbe rappresentare il momento appena prima di generare il contenuto del messaggio. In pratica, un mittente può generare il valore della data in qualsiasi momento durante l'origine del messaggio.

Un server di origine con un orologio (come definito nella Sezione 5.6.7) DEVE (MUST) generare un campo di header Date in tutte le risposte 2xx (Successful), 3xx (Redirection) e 4xx (Client Error), e PUÒ (MAY) generare un campo di header Date nelle risposte 1xx (Informational) e 5xx (Server Error).

Un server di origine senza orologio NON DEVE (MUST NOT) generare un campo di header Date.

Un destinatario con un orologio che riceve un messaggio di risposta senza un campo di header Date DEVE (MUST) registrare l'ora in cui è stato ricevuto e aggiungere un campo di header Date corrispondente alla sezione di header del messaggio se viene memorizzato nella cache o inoltrato downstream.

Un destinatario con un orologio che riceve una risposta con un valore di campo di header Date non valido PUÒ (MAY) sostituire quel valore con l'ora in cui è stata ricevuta quella risposta.

Un agente utente PUÒ (MAY) inviare un campo di header Date in una richiesta, sebbene generalmente non lo faccia a meno che non si ritenga che trasmetta informazioni utili al server. Ad esempio, applicazioni personalizzate di HTTP potrebbero trasmettere una Date se il server è previsto che regoli la sua interpretazione della richiesta dell'utente in base alle differenze tra gli orologi dell'agente utente e del server.

6.6.2. Trailer

Il campo di header "Trailer" fornisce un elenco di nomi di campo che il mittente prevede di inviare come campi di trailer all'interno di quel messaggio. Ciò consente a un destinatario di prepararsi per la ricezione dei metadati indicati prima di iniziare a elaborare il contenuto.

Trailer = #field-name

Ad esempio, un mittente potrebbe indicare che una firma verrà calcolata mentre il contenuto viene trasmesso in streaming e fornire la firma finale come campo di trailer. Ciò consente a un destinatario di eseguire lo stesso controllo al volo mentre riceve il contenuto.

Un mittente che intende generare uno o più campi di trailer in un messaggio DOVREBBE (SHOULD) generare un campo di header Trailer nella sezione di header di quel messaggio per indicare quali campi potrebbero essere presenti nei trailer.

Se un intermediario scarta la sezione di trailer durante il transito, il campo Trailer potrebbe fornire un indizio su quali metadati sono stati persi, sebbene non vi sia alcuna garanzia che un mittente di Trailer seguirà sempre inviando i campi nominati.