Passa al contenuto principale

4. HTTP Frames (Frame HTTP)

Una volta stabilita la connessione HTTP/2, gli endpoint possono iniziare a scambiare frame.

4.1. Frame Format (Formato del frame)

Tutti i frame iniziano con un'intestazione fissa di 9 ottetti seguita da un payload di frame di lunghezza variabile.

HTTP Frame {
Length (24),
Type (8),

Flags (8),

Reserved (1),
Stream Identifier (31),

Frame Payload (..),
}

Figura 1: Layout del frame

I campi dell'intestazione del frame sono definiti come segue:

Length (Lunghezza): La lunghezza del payload del frame espressa come intero senza segno a 24 bit in unità di ottetti. I valori maggiori di 2^14 (16.384) non devono (MUST NOT) essere inviati a meno che il ricevitore non abbia impostato un valore maggiore per SETTINGS_MAX_FRAME_SIZE.

I 9 ottetti dell'intestazione del frame non sono inclusi in questo valore.

Type (Tipo): Il tipo a 8 bit del frame. Il tipo di frame determina il formato e la semantica del frame. I frame definiti in questo documento sono elencati nella sezione 6. Le implementazioni devono (MUST) ignorare e scartare i frame di tipi sconosciuti.

Flags (Flag): Un campo a 8 bit riservato per flag booleani specifici del tipo di frame.

Ai flag vengono assegnate semantiche specifiche per il tipo di frame indicato. I flag non utilizzati sono quelli che non hanno semantiche definite per un particolare tipo di frame. I flag non utilizzati devono (MUST) essere ignorati alla ricezione e devono (MUST) rimanere non impostati (0x00) durante l'invio.

Reserved (Riservato): Un campo riservato di 1 bit. La semantica di questo bit non è definita e il bit deve (MUST) rimanere non impostato (0x00) durante l'invio e deve (MUST) essere ignorato durante la ricezione.

Stream Identifier (Identificatore di stream): Un identificatore di stream (vedere sezione 5.1.1) espresso come intero senza segno a 31 bit. Il valore 0x00 è riservato per i frame associati alla connessione nel suo complesso anziché a un singolo stream.

La struttura e il contenuto del payload del frame dipendono interamente dal tipo di frame.

4.2. Frame Size (Dimensione del frame)

La dimensione del payload di un frame è limitata dalla dimensione massima che un ricevitore annuncia nell'impostazione SETTINGS_MAX_FRAME_SIZE. Questa impostazione può avere qualsiasi valore tra 2^14 (16.384) e 2^24-1 (16.777.215) ottetti, inclusi.

Tutte le implementazioni devono (MUST) essere in grado di ricevere ed elaborare minimamente frame fino a 2^14 ottetti di lunghezza, più l'intestazione del frame di 9 ottetti (sezione 4.1). La dimensione dell'intestazione del frame non è inclusa nella descrizione delle dimensioni dei frame.

Nota: Alcuni tipi di frame, come PING (sezione 6.7), impongono limiti aggiuntivi sulla quantità di dati del payload del frame consentita.

Un endpoint deve (MUST) inviare un codice di errore FRAME_SIZE_ERROR se un frame supera la dimensione definita in SETTINGS_MAX_FRAME_SIZE, supera qualsiasi limite definito per il tipo di frame o è troppo piccolo per contenere dati di frame obbligatori. Un errore di dimensione del frame in un frame che potrebbe alterare lo stato dell'intera connessione deve (MUST) essere trattato come un errore di connessione (sezione 5.4.1); ciò include qualsiasi frame che trasporta un blocco di campi (Field Block, sezione 4.3) (cioè HEADERS, PUSH_PROMISE e CONTINUATION), un frame SETTINGS e qualsiasi frame con un identificatore di stream di 0.

Gli endpoint non sono obbligati a utilizzare tutto lo spazio disponibile in un frame. La reattività può essere migliorata utilizzando frame più piccoli della dimensione massima consentita. L'invio di frame di grandi dimensioni può comportare ritardi nell'invio di frame sensibili al tempo (come RST_STREAM, WINDOW_UPDATE o PRIORITY), che, se bloccati dalla trasmissione di un frame di grandi dimensioni, potrebbero influire sulle prestazioni.

4.3. Field Section Compression and Decompression (Compressione e decompressione della sezione di campi)

La compressione della sezione di campi (Field Section Compression) è il processo di compressione di un insieme di righe di campi (sezione 5.2 di [HTTP]) per formare un blocco di campi (Field Block). La decompressione della sezione di campi (Field Section Decompression) è il processo di decodifica di un blocco di campi in un insieme di righe di campi. I dettagli della compressione e decompressione della sezione di campi HTTP/2 sono definiti in [COMPRESSION], che, per ragioni storiche, si riferisce a questi processi come compressione e decompressione dell'intestazione.

Ogni blocco di campi trasporta tutte le righe di campi compresse di una singola sezione di campi. Le sezioni di intestazione includono anche dati di controllo associati al messaggio sotto forma di campi di intestazione pseudo (Pseudo-Header Fields, sezione 8.3) che utilizzano lo stesso formato di una riga di campo.

Nota: RFC 7540 [RFC7540] utilizzava il termine "blocco di intestazione (Header Block)" al posto del più generico "blocco di campi (Field Block)".

I blocchi di campi trasportano dati di controllo e sezioni di intestazione per richieste, risposte, richieste promesse e risposte spinte (vedere sezione 8.4). Tutti questi messaggi, ad eccezione delle risposte provvisorie e delle richieste contenute nei frame PUSH_PROMISE (sezione 6.6), possono facoltativamente includere un blocco di campi che trasporta una sezione trailer.

Una sezione di campi è una raccolta di righe di campi. Ciascuna delle righe di campi in un blocco di campi trasporta un singolo valore. Il blocco di campi serializzato viene quindi diviso in una o più sequenze di ottetti, chiamate frammenti di blocco di campi (Field Block Fragments). Il primo frammento di blocco di campi viene trasmesso all'interno del payload del frame di HEADERS (sezione 6.2) o PUSH_PROMISE (sezione 6.6), ciascuno dei quali potrebbe essere seguito da frame CONTINUATION (sezione 6.10) per trasportare frammenti di blocco di campi successivi.

Il campo di intestazione Cookie [COOKIE] è trattato in modo speciale dalla mappatura HTTP (vedere sezione 8.2.3).

Un endpoint ricevente riassembla il blocco di campi concatenando i suoi frammenti e quindi decomprime il blocco per ricostruire la sezione di campi.

Una sezione di campi completa consiste in:

  • un singolo frame HEADERS o PUSH_PROMISE, con il flag END_HEADERS impostato, oppure

  • un frame HEADERS o PUSH_PROMISE con il flag END_HEADERS non impostato e uno o più frame CONTINUATION, dove l'ultimo frame CONTINUATION ha il flag END_HEADERS impostato.

Ogni blocco di campi viene elaborato come un'unità discreta. I blocchi di campi devono (MUST) essere trasmessi come una sequenza contigua di frame, senza frame intercalati di nessun altro tipo o da qualsiasi altro stream. L'ultimo frame in una sequenza di frame HEADERS o CONTINUATION ha il flag END_HEADERS impostato. L'ultimo frame in una sequenza di frame PUSH_PROMISE o CONTINUATION ha il flag END_HEADERS impostato. Ciò consente a un blocco di campi di essere logicamente equivalente a un singolo frame.

I frammenti di blocco di campi possono essere inviati solo come payload di frame dei frame HEADERS, PUSH_PROMISE o CONTINUATION perché questi frame trasportano dati che possono modificare il contesto di compressione mantenuto da un ricevitore. Un endpoint che riceve frame HEADERS, PUSH_PROMISE o CONTINUATION deve riassemblare i blocchi di campi ed eseguire la decompressione anche se i frame devono essere scartati. Un ricevitore deve (MUST) terminare la connessione con un errore di connessione (sezione 5.4.1) di tipo COMPRESSION_ERROR se non decomprime un blocco di campi.

Un errore di decodifica in un blocco di campi deve (MUST) essere trattato come un errore di connessione (sezione 5.4.1) di tipo COMPRESSION_ERROR.

4.3.1. Compression State (Stato di compressione)

La compressione dei campi è con stato. Ogni endpoint ha un contesto di codificatore HPACK e un contesto di decodificatore HPACK che vengono utilizzati per codificare e decodificare tutti i blocchi di campi su una connessione. La sezione 4 di [COMPRESSION] definisce la tabella dinamica, che è lo stato primario per ogni contesto.

La tabella dinamica ha una dimensione massima impostata da un decodificatore HPACK. Un endpoint comunica la dimensione scelta dal suo contesto di decodificatore HPACK utilizzando l'impostazione SETTINGS_HEADER_TABLE_SIZE; vedere sezione 6.5.2. Quando viene stabilita una connessione, la dimensione della tabella dinamica per il decodificatore e il codificatore HPACK presso entrambi gli endpoint inizia a 4.096 byte, il valore iniziale dell'impostazione SETTINGS_HEADER_TABLE_SIZE.

Qualsiasi modifica al valore massimo impostato utilizzando SETTINGS_HEADER_TABLE_SIZE ha effetto quando l'endpoint riconosce le impostazioni (sezione 6.5.3). Il codificatore HPACK presso quell'endpoint può impostare la tabella dinamica a qualsiasi dimensione fino al valore massimo impostato dal decodificatore. Un codificatore HPACK dichiara la dimensione della tabella dinamica con un'istruzione Dynamic Table Size Update (sezione 6.3 di [COMPRESSION]).

Una volta che un endpoint riconosce una modifica a SETTINGS_HEADER_TABLE_SIZE che riduce il massimo al di sotto della dimensione corrente della tabella dinamica, il suo codificatore HPACK deve (MUST) iniziare il blocco di campi successivo con un'istruzione Dynamic Table Size Update che imposta la tabella dinamica a una dimensione minore o uguale al massimo ridotto; vedere sezione 4.2 di [COMPRESSION]. Un endpoint deve (MUST) trattare un blocco di campi che segue un riconoscimento della riduzione alla dimensione massima della tabella dinamica come un errore di connessione (sezione 5.4.1) di tipo COMPRESSION_ERROR se non inizia con un'istruzione Dynamic Table Size Update conforme.

Nota: Gli implementatori sono informati che la riduzione del valore di SETTINGS_HEADER_TABLE_SIZE non è ampiamente interoperabile. L'uso della prefazione di connessione per ridurre il valore al di sotto del valore iniziale di 4.096 è in qualche modo meglio supportato, ma questo potrebbe fallire con alcune implementazioni.