4. Espressione della semantica HTTP in HTTP/3 (Expressing HTTP Semantics in HTTP/3)
4.1. Frame dei messaggi HTTP (HTTP Message Framing)
Un client invia una richiesta HTTP su un flusso di richiesta (Request Stream), che è un flusso QUIC bidirezionale avviato dal client; vedere la sezione 6.1. Un client DEVE (MUST) inviare solo una singola richiesta su un dato flusso. Un server invia zero o più risposte HTTP provvisorie (Interim HTTP Responses) sullo stesso flusso della richiesta, seguite da una singola risposta HTTP finale (Final HTTP Response), come descritto di seguito. Vedere la sezione 15 di [HTTP] per una descrizione delle risposte HTTP provvisorie e finali.
Le risposte push (Pushed Responses) vengono inviate su un flusso QUIC unidirezionale avviato dal server; vedere la sezione 6.2.2. Un server invia zero o più risposte HTTP provvisorie, seguite da una singola risposta HTTP finale, nello stesso modo di una risposta standard. Il push è descritto più in dettaglio nella sezione 4.6.
Su un dato flusso, la ricezione di più richieste o la ricezione di una risposta HTTP aggiuntiva dopo una risposta HTTP finale DEVE (MUST) essere trattata come malformata (Malformed).
Un messaggio HTTP (richiesta o risposta) è composto da:
-
la sezione di intestazione (Header Section), che include i dati di controllo del messaggio, inviata come un singolo frame HEADERS,
-
opzionalmente, il contenuto (Content), se presente, inviato come una serie di frame DATA, e
-
opzionalmente, la sezione trailer (Trailer Section), se presente, inviata come un singolo frame HEADERS.
Le sezioni di intestazione e trailer sono descritte nelle sezioni 6.3 e 6.5 di [HTTP]; il contenuto è descritto nella sezione 6.4 di [HTTP].
La ricezione di una sequenza di frame non valida DEVE (MUST) essere trattata come un errore di connessione (Connection Error) di tipo H3_FRAME_UNEXPECTED. In particolare, un frame DATA prima di qualsiasi frame HEADERS, o un frame HEADERS o DATA dopo il frame HEADERS finale, è considerato non valido. Altri tipi di frame, in particolare i tipi di frame sconosciuti, potrebbero essere consentiti soggetti alle proprie regole; vedere la sezione 9.
Un server PUÒ (MAY) inviare uno o più frame PUSH_PROMISE prima, dopo o intercalati con i frame di un messaggio di risposta. Questi frame PUSH_PROMISE non fanno parte della risposta; vedere la sezione 4.6 per maggiori dettagli. I frame PUSH_PROMISE non sono consentiti sui flussi push; una risposta push che include frame PUSH_PROMISE DEVE (MUST) essere trattata come un errore di connessione di tipo H3_FRAME_UNEXPECTED.
I frame di tipo sconosciuto (sezione 9), inclusi i frame riservati (Reserved Frames) (sezione 7.2.8), POSSONO (MAY) essere inviati su un flusso di richiesta o push prima, dopo o intercalati con altri frame descritti in questa sezione.
I frame HEADERS e PUSH_PROMISE potrebbero fare riferimento ad aggiornamenti della tabella dinamica QPACK (Dynamic Table). Sebbene questi aggiornamenti non facciano direttamente parte dello scambio di messaggi, devono essere ricevuti ed elaborati prima che il messaggio possa essere consumato. Vedere la sezione 4.2 per maggiori dettagli.
Le codifiche di trasferimento (Transfer Codings) (vedere la sezione 7 di [HTTP/1.1]) non sono definite per HTTP/3; il campo di intestazione Transfer-Encoding NON DEVE (MUST NOT) essere utilizzato.
Una risposta PUÒ (MAY) essere composta da più messaggi se e solo se una o più risposte provvisorie (1xx; vedere la sezione 15.2 di [HTTP]) precedono una risposta finale alla stessa richiesta. Le risposte provvisorie non contengono contenuto o sezioni trailer.
Uno scambio di richiesta/risposta HTTP consuma completamente un flusso QUIC bidirezionale avviato dal client. Dopo aver inviato una richiesta, un client DEVE (MUST) chiudere il flusso per l'invio. A meno che non si utilizzi il metodo CONNECT (vedere la sezione 4.4), i client NON DEVONO (MUST NOT) rendere la chiusura del flusso dipendente dalla ricezione di una risposta alla loro richiesta. Dopo aver inviato una risposta finale, il server DEVE (MUST) chiudere il flusso per l'invio. A questo punto, il flusso QUIC è completamente chiuso.
Quando un flusso viene chiuso, ciò indica la fine del messaggio HTTP finale. Poiché alcuni messaggi sono grandi o illimitati, gli endpoint DOVREBBERO (SHOULD) iniziare a elaborare messaggi HTTP parziali una volta che è stata ricevuta una quantità sufficiente del messaggio per fare progressi. Se un flusso avviato dal client termina senza una quantità sufficiente del messaggio HTTP per fornire una risposta completa, il server DOVREBBE (SHOULD) interrompere il proprio flusso di risposta con il codice di errore H3_REQUEST_INCOMPLETE.
Un server può inviare una risposta completa prima che il client invii un'intera richiesta se la risposta non dipende da alcuna parte della richiesta che non è stata inviata e ricevuta. Quando il server non ha bisogno di ricevere il resto della richiesta, PUÒ (MAY) interrompere la lettura del flusso di richiesta, inviare una risposta completa e chiudere in modo pulito la parte di invio del flusso. Il codice di errore H3_NO_ERROR DOVREBBE (SHOULD) essere utilizzato quando si richiede al client di interrompere l'invio sul flusso di richiesta. I client NON DEVONO (MUST NOT) scartare le risposte complete a seguito dell'interruzione brusca della loro richiesta, sebbene i client possano sempre scartare le risposte a loro discrezione per altri motivi. Se il server invia una risposta parziale o completa ma non interrompe la lettura della richiesta, i client DOVREBBERO (SHOULD) continuare a inviare il contenuto della richiesta e chiudere il flusso normalmente.
4.1.1. Annullamento e rifiuto della richiesta (Request Cancellation and Rejection)
Una volta aperto un flusso di richiesta, la richiesta PUÒ (MAY) essere annullata da uno dei due endpoint. I client annullano le richieste se la risposta non è più di interesse; i server annullano le richieste se non sono in grado o scelgono di non rispondere. Quando possibile, si RACCOMANDA (RECOMMENDED) che i server inviino una risposta HTTP con un codice di stato appropriato piuttosto che annullare una richiesta la cui elaborazione è già iniziata.
Le implementazioni DOVREBBERO (SHOULD) annullare le richieste terminando bruscamente tutte le direzioni di un flusso ancora aperte. Per fare ciò, un'implementazione reimposta le parti di invio dei flussi e interrompe la lettura delle parti di ricezione dei flussi; vedere la sezione 2.4 di [QUIC-TRANSPORT].
Quando il server annulla una richiesta senza eseguire alcuna elaborazione dell'applicazione, la richiesta è considerata "rifiutata" (Rejected). Il server DOVREBBE (SHOULD) interrompere il proprio flusso di risposta con il codice di errore H3_REQUEST_REJECTED. In questo contesto, "elaborato" (Processed) significa che alcuni dati dal flusso sono stati passati a un livello software superiore che potrebbe aver intrapreso qualche azione di conseguenza. Il client può trattare le richieste rifiutate dal server come se non fossero mai state inviate, consentendo così di ritentarle successivamente.
I server NON DEVONO (MUST NOT) utilizzare il codice di errore H3_REQUEST_REJECTED per le richieste che sono state elaborate parzialmente o completamente. Quando un server abbandona una risposta dopo un'elaborazione parziale, DOVREBBE (SHOULD) interrompere il proprio flusso di risposta con il codice di errore H3_REQUEST_CANCELLED.
Il client DOVREBBE (SHOULD) utilizzare il codice di errore H3_REQUEST_CANCELLED per annullare le richieste. Alla ricezione di questo codice di errore, un server PUÒ (MAY) terminare bruscamente la risposta utilizzando il codice di errore H3_REQUEST_REJECTED se non è stata eseguita alcuna elaborazione. I client NON DEVONO (MUST NOT) utilizzare il codice di errore H3_REQUEST_REJECTED, a meno che un server non abbia richiesto la chiusura del flusso di richiesta con questo codice di errore.
Se un flusso viene annullato dopo aver ricevuto una risposta completa, il client PUÒ (MAY) ignorare l'annullamento e utilizzare la risposta. Tuttavia, se un flusso viene annullato dopo aver ricevuto una risposta parziale, la risposta NON DOVREBBE (SHOULD NOT) essere utilizzata. Solo le azioni idempotenti (Idempotent Actions) come GET, PUT o DELETE possono essere ritentate in sicurezza; un client NON DOVREBBE (SHOULD NOT) ritentare automaticamente una richiesta con un metodo non idempotente a meno che non abbia un modo per sapere che la semantica della richiesta è idempotente indipendentemente dal metodo o un modo per rilevare che la richiesta originale non è mai stata applicata. Vedere la sezione 9.2.2 di [HTTP] per maggiori dettagli.
4.1.2. Richieste e risposte malformate (Malformed Requests and Responses)
Una richiesta o una risposta malformata è una sequenza di frame altrimenti valida ma non valida a causa di:
-
la presenza di campi proibiti o campi pseudo-intestazione (Pseudo-Header Fields),
-
l'assenza di campi pseudo-intestazione obbligatori,
-
valori non validi per i campi pseudo-intestazione,
-
campi pseudo-intestazione dopo i campi,
-
una sequenza non valida di messaggi HTTP,
-
l'inclusione di nomi di campo in maiuscolo, o
-
l'inclusione di caratteri non validi nei nomi o valori dei campi.
Una richiesta o una risposta definita come avente contenuto quando contiene un campo di intestazione Content-Length (sezione 8.6 di [HTTP]) è malformata se il valore del campo di intestazione Content-Length non è uguale alla somma delle lunghezze dei frame DATA ricevuti. Una risposta definita come mai avente contenuto, anche quando è presente un Content-Length, può avere un campo di intestazione Content-Length diverso da zero anche se non è incluso alcun contenuto nei frame DATA.
Gli intermediari che elaborano richieste o risposte HTTP (cioè qualsiasi intermediario che non agisce come un tunnel) NON DEVONO (MUST NOT) inoltrare una richiesta o una risposta malformata. Le richieste o le risposte malformate rilevate DEVONO (MUST) essere trattate come un errore di flusso (Stream Error) di tipo H3_MESSAGE_ERROR.
Per le richieste malformate, un server PUÒ (MAY) inviare una risposta HTTP che indica l'errore prima di chiudere o reimpostare il flusso. I client NON DEVONO (MUST NOT) accettare una risposta malformata. Si noti che questi requisiti sono intesi a proteggere contro diversi tipi di attacchi comuni contro HTTP; sono deliberatamente rigorosi perché essere permissivi può esporre le implementazioni a queste vulnerabilità.
4.2. Campi HTTP (HTTP Fields)
I messaggi HTTP trasportano metadati come una serie di coppie chiave-valore chiamate "campi HTTP" (HTTP Fields); vedere le sezioni 6.3 e 6.5 di [HTTP]. Per un elenco dei campi HTTP registrati, vedere il "Registro dei nomi dei campi del protocollo di trasferimento ipertestuale (HTTP)" (Hypertext Transfer Protocol (HTTP) Field Name Registry) mantenuto su https://www.iana.org/assignments/http-fields/. Come HTTP/2, HTTP/3 ha considerazioni aggiuntive relative all'uso di caratteri nei nomi dei campi, al campo di intestazione Connection e ai campi pseudo-intestazione.
I nomi dei campi sono stringhe contenenti un sottoinsieme di caratteri ASCII. Le proprietà dei nomi e dei valori dei campi HTTP sono discusse più in dettaglio nella sezione 5.1 di [HTTP]. I caratteri nei nomi dei campi DEVONO (MUST) essere convertiti in minuscolo prima della loro codifica. Una richiesta o una risposta contenente caratteri maiuscoli nei nomi dei campi DEVE (MUST) essere trattata come malformata.
HTTP/3 non utilizza il campo di intestazione Connection per indicare campi specifici della connessione; in questo protocollo, i metadati specifici della connessione sono trasmessi con altri mezzi. Un endpoint NON DEVE (MUST NOT) generare una sezione di campo HTTP/3 contenente campi specifici della connessione; qualsiasi messaggio contenente campi specifici della connessione DEVE (MUST) essere trattato come malformato.
L'unica eccezione a questo è il campo di intestazione TE, che PUÒ (MAY) essere presente in un'intestazione di richiesta HTTP/3; quando lo è, NON DEVE (MUST NOT) contenere alcun valore diverso da "trailers".
Un intermediario che trasforma un messaggio HTTP/1.x in HTTP/3 DEVE (MUST) rimuovere i campi di intestazione specifici della connessione come discusso nella sezione 7.6.1 di [HTTP], altrimenti i loro messaggi saranno trattati da altri endpoint HTTP/3 come malformati.
4.2.1. Compressione dei campi (Field Compression)
[QPACK] descrive una variazione di HPACK che dà a un codificatore un certo controllo su quanto blocco head-of-line (Head-of-Line Blocking) può essere causato dalla compressione. Questo consente a un codificatore di bilanciare l'efficienza della compressione con la latenza. HTTP/3 utilizza QPACK per comprimere le sezioni di intestazione e trailer, inclusi i dati di controllo presenti nella sezione di intestazione.
Per consentire una migliore efficienza di compressione, il campo di intestazione Cookie ([COOKIES]) PUÒ (MAY) essere suddiviso in righe di campo separate, ciascuna con una o più coppie di cookie (Cookie-Pairs), prima della compressione. Se una sezione di campo decompressa contiene più righe di campo cookie, queste DEVONO (MUST) essere concatenate in una singola stringa di byte utilizzando il delimitatore di due byte "; " (ASCII 0x3b, 0x20) prima di essere passate in un contesto diverso da HTTP/2 o HTTP/3, come una connessione HTTP/1.1 o un'applicazione server HTTP generica.
4.2.2. Vincoli sulla dimensione dell'intestazione (Header Size Constraints)
Un'implementazione HTTP/3 PUÒ (MAY) imporre un limite sulla dimensione massima dell'intestazione del messaggio che accetterà su un singolo messaggio HTTP. Un server che riceve una sezione di intestazione più grande di quella che è disposto a gestire può inviare un codice di stato HTTP 431 (Request Header Fields Too Large) ([RFC6585]). Un client può scartare le risposte che non può elaborare. La dimensione di un elenco di campi è calcolata in base alla dimensione non compressa dei campi, inclusa la lunghezza del nome e del valore in byte più un overhead di 32 byte per ogni campo.
Se un'implementazione desidera informare il suo peer di questo limite, può essere trasmesso come numero di byte nel parametro SETTINGS_MAX_FIELD_SECTION_SIZE. Un'implementazione che ha ricevuto questo parametro NON DOVREBBE (SHOULD NOT) inviare un'intestazione di messaggio HTTP che supera la dimensione indicata, poiché è probabile che il peer rifiuti di elaborarla. Tuttavia, un messaggio HTTP può attraversare uno o più intermediari prima di raggiungere il server di origine; vedere la sezione 3.7 di [HTTP]. Poiché questo limite viene applicato separatamente da ogni implementazione che elabora il messaggio, i messaggi al di sotto di questo limite non sono garantiti di essere accettati.
4.3. Dati di controllo HTTP (HTTP Control Data)
Come HTTP/2, HTTP/3 utilizza una serie di campi pseudo-intestazione (Pseudo-Header Fields), dove il nome del campo inizia con il carattere : (ASCII 0x3a). Questi campi pseudo-intestazione trasmettono i dati di controllo del messaggio; vedere la sezione 6.2 di [HTTP].
I campi pseudo-intestazione non sono campi HTTP. Gli endpoint NON DEVONO (MUST NOT) generare campi pseudo-intestazione diversi da quelli definiti in questo documento. Tuttavia, un'estensione potrebbe negoziare una modifica di questa restrizione; vedere la sezione 9.
I campi pseudo-intestazione sono validi solo nel contesto in cui sono definiti. I campi pseudo-intestazione definiti per le richieste NON DEVONO (MUST NOT) apparire nelle risposte; i campi pseudo-intestazione definiti per le risposte NON DEVONO (MUST NOT) apparire nelle richieste. I campi pseudo-intestazione NON DEVONO (MUST NOT) apparire nelle sezioni trailer. Gli endpoint DEVONO (MUST) trattare una richiesta o una risposta che contiene campi pseudo-intestazione non definiti o non validi come malformata.
Tutti i campi pseudo-intestazione DEVONO (MUST) apparire nella sezione di intestazione prima dei campi di intestazione regolari. Qualsiasi richiesta o risposta che contiene un campo pseudo-intestazione che appare in una sezione di intestazione dopo un campo di intestazione regolare DEVE (MUST) essere trattata come malformata.
4.3.1. Campi pseudo-intestazione di richiesta (Request Pseudo-Header Fields)
I seguenti campi pseudo-intestazione sono definiti per le richieste:
":method": Contiene il metodo HTTP (HTTP Method) (sezione 9 di [HTTP])
":scheme": Contiene la parte scheme dell'URI di destinazione (sezione 3.1 di [URI]).
Il pseudo-intestazione :scheme non è limitato agli URI con scheme "http" e "https". Un proxy o gateway può tradurre richieste per scheme non HTTP, consentendo l'uso di HTTP per interagire con servizi non HTTP.
Vedere la sezione 3.1.2 per indicazioni sull'uso di uno scheme diverso da "https".
":authority": Contiene la parte authority dell'URI di destinazione (sezione 3.2 di [URI]). L'authority NON DEVE (MUST NOT) includere il sottocomponente userinfo deprecato per gli URI con scheme "http" o "https".
Per garantire che la riga di richiesta HTTP/1.1 possa essere riprodotta accuratamente, questo campo pseudo-intestazione DEVE (MUST) essere omesso durante la traduzione da una richiesta HTTP/1.1 che ha un target di richiesta in una forma specifica del metodo; vedere la sezione 7.1 di [HTTP]. I client che generano richieste HTTP/3 direttamente DOVREBBERO (SHOULD) utilizzare il campo pseudo-intestazione :authority invece del campo di intestazione Host. Un intermediario che converte una richiesta HTTP/3 in HTTP/1.1 DEVE (MUST) creare un campo Host se non presente in una richiesta copiando il valore del campo pseudo-intestazione :authority.
":path": Contiene le parti path e query dell'URI di destinazione (la produzione "path-absolute" e opzionalmente un carattere ? (ASCII 0x3f) seguito dalla produzione "query"; vedere le sezioni 3.3 e 3.4 di [URI]).
Questo campo pseudo-intestazione NON DEVE (MUST NOT) essere vuoto per gli URI "http" o "https"; gli URI "http" o "https" che non contengono un componente path DEVONO (MUST) includere un valore di / (ASCII 0x2f). Una richiesta OPTIONS che non include un componente path include il valore * (ASCII 0x2a) per il campo pseudo-intestazione :path; vedere la sezione 7.1 di [HTTP].
Tutte le richieste HTTP/3 DEVONO (MUST) includere esattamente un valore per i campi pseudo-intestazione :method, :scheme e :path, a meno che la richiesta non sia una richiesta CONNECT; vedere la sezione 4.4.
Se il campo pseudo-intestazione :scheme identifica uno scheme che ha un componente authority obbligatorio (inclusi "http" e "https"), la richiesta DEVE (MUST) contenere un campo pseudo-intestazione :authority o un campo di intestazione Host. Se questi campi sono presenti, NON DEVONO (MUST NOT) essere vuoti. Se entrambi i campi sono presenti, DEVONO (MUST) contenere lo stesso valore. Se lo scheme non ha un componente authority obbligatorio e nessuno è fornito nel target di richiesta, la richiesta NON DEVE (MUST NOT) contenere il pseudo-intestazione :authority o i campi di intestazione Host.
Una richiesta HTTP che omette i campi pseudo-intestazione obbligatori o contiene valori non validi per tali campi pseudo-intestazione è malformata.
HTTP/3 non definisce un modo per trasportare l'identificatore di versione incluso nella riga di richiesta HTTP/1.1. Le richieste HTTP/3 hanno implicitamente una versione di protocollo "3.0".
4.3.2. Campi pseudo-intestazione di risposta (Response Pseudo-Header Fields)
Per le risposte, è definito un singolo campo pseudo-intestazione ":status" che trasporta il codice di stato HTTP; vedere la sezione 15 di [HTTP]. Questo campo pseudo-intestazione DEVE (MUST) essere incluso in tutte le risposte; altrimenti, la risposta è malformata (vedere la sezione 4.1.2).
HTTP/3 non definisce un modo per trasportare la versione o la frase di motivo (Reason Phrase) inclusa in una riga di stato HTTP/1.1. Le risposte HTTP/3 hanno implicitamente una versione di protocollo "3.0".
4.4. Il metodo CONNECT (The CONNECT Method)
Il metodo CONNECT richiede al destinatario di stabilire un tunnel (Tunnel) al server di origine di destinazione identificato dal target di richiesta; vedere la sezione 9.3.6 di [HTTP]. Viene utilizzato principalmente con i proxy HTTP per stabilire una sessione TLS con un server di origine allo scopo di interagire con risorse "https".
In HTTP/1.x, CONNECT viene utilizzato per convertire un'intera connessione HTTP in un tunnel verso un host remoto. In HTTP/2 e HTTP/3, il metodo CONNECT viene utilizzato per stabilire un tunnel su un singolo flusso.
Una richiesta CONNECT DEVE (MUST) essere costruita come segue:
-
Il campo pseudo-intestazione :method è impostato su "CONNECT"
-
I campi pseudo-intestazione :scheme e :path sono omessi
-
Il campo pseudo-intestazione :authority contiene l'host e la porta a cui connettersi (equivalente alla forma authority del target di richiesta delle richieste CONNECT; vedere la sezione 7.1 di [HTTP]).
Il flusso di richiesta rimane aperto alla fine della richiesta per trasportare i dati da trasferire. Una richiesta CONNECT che non rispetta queste restrizioni è malformata.
Un proxy che supporta CONNECT stabilisce una connessione TCP ([RFC0793]) al server identificato nel campo pseudo-intestazione :authority. Una volta che questa connessione è stata stabilita con successo, il proxy invia un frame HEADERS contenente un codice di stato della serie 2xx al client, come definito nella sezione 15.3 di [HTTP].
Tutti i frame DATA sul flusso corrispondono ai dati inviati o ricevuti sulla connessione TCP. Il payload di qualsiasi frame DATA inviato dal client viene trasmesso dal proxy al server TCP; i dati ricevuti dal server TCP vengono impacchettati in frame DATA dal proxy. Si noti che la dimensione e il numero di segmenti TCP non sono garantiti per mappare in modo prevedibile alla dimensione e al numero di frame HTTP DATA o QUIC STREAM.
Una volta completato il metodo CONNECT, solo i frame DATA sono consentiti per essere inviati sul flusso. I frame di estensione POSSONO (MAY) essere utilizzati se specificamente consentiti dalla definizione dell'estensione. La ricezione di qualsiasi altro tipo di frame noto DEVE (MUST) essere trattata come un errore di connessione di tipo H3_FRAME_UNEXPECTED.
La connessione TCP può essere chiusa da uno dei due peer. Quando il client termina il flusso di richiesta (cioè il flusso di ricezione al proxy entra nello stato "Data Recvd"), il proxy imposterà il bit FIN sulla sua connessione al server TCP. Quando il proxy riceve un pacchetto con il bit FIN impostato, chiuderà il flusso di invio che invia al client. Le connessioni TCP che rimangono semichiuse (Half-Closed) in una singola direzione non sono invalide, ma sono spesso gestite male dai server, quindi i client NON DOVREBBERO (SHOULD NOT) chiudere un flusso per l'invio mentre si aspettano ancora di ricevere dati dal target del CONNECT.
Un errore di connessione TCP viene segnalato terminando bruscamente il flusso. Un proxy tratta qualsiasi errore nella connessione TCP, che include la ricezione di un segmento TCP con il bit RST impostato, come un errore di flusso di tipo H3_CONNECT_ERROR.
Di conseguenza, se un proxy rileva un errore con il flusso o la connessione QUIC, DEVE (MUST) chiudere la connessione TCP. Se il proxy rileva che il client ha reimpostato il flusso o interrotto la lettura dal flusso, DEVE (MUST) chiudere la connessione TCP. Se il flusso viene reimpostato o la lettura viene interrotta dal client, un proxy DOVREBBE (SHOULD) eseguire la stessa operazione nell'altra direzione per garantire che entrambe le direzioni del flusso vengano annullate. In tutti questi casi, se l'implementazione TCP sottostante lo consente, il proxy DOVREBBE (SHOULD) inviare un segmento TCP con il bit RST impostato.
Poiché CONNECT crea un tunnel verso un server arbitrario, i proxy che supportano CONNECT DOVREBBERO (SHOULD) limitarne l'uso a un set di porte note o a un elenco di target di richiesta sicuri; vedere la sezione 9.3.6 di [HTTP] per maggiori dettagli.
4.5. Upgrade HTTP (HTTP Upgrade)
HTTP/3 non supporta il meccanismo di upgrade HTTP (HTTP Upgrade Mechanism) (sezione 7.8 di [HTTP]) o il codice di stato informativo 101 (Switching Protocols) (sezione 15.2.2 di [HTTP]).
4.6. Push del server (Server Push)
Il push del server (Server Push) è una modalità di interazione che consente a un server di inviare uno scambio richiesta-risposta a un client in previsione della richiesta del client. Un client può disabilitare il push del server impostando SETTINGS_ENABLE_PUSH su 0 in un frame SETTINGS. Un server NON DEVE (MUST NOT) inviare un push a un client che ha impostato SETTINGS_ENABLE_PUSH su 0; il comportamento del server che viola questo DEVE (MUST) essere trattato come un errore di connessione di tipo H3_SETTINGS_ERROR.
Come HTTP/2, il server avvia un push inviando un frame PUSH_PROMISE (sezione 7.2.5) su un flusso di richiesta avviato dal client. L'ID push (Push ID) viene utilizzato per identificare un push del server (vedere la sezione 4.6.1). L'ID push viene trasportato nel frame PUSH_PROMISE, che include anche una sezione di intestazione di richiesta attribuita alla richiesta generata dal server, come descritto nella sezione 15 di [HTTP].
Il server invia la risposta da un flusso push che avvia (sezione 6.2.2). La consegna della risposta push è identica a quella di una risposta a una richiesta regolare. La sezione di intestazione della risposta per la risposta push viene trasportata in un frame HEADERS come descritto nella sezione 7.2.4. Un server può annullare un push promesso inviando un frame CANCEL_PUSH con l'ID push sul flusso push.
I client controllano il numero di push che il server può promettere utilizzando il frame MAX_PUSH_ID (sezione 7.2.7). Un server NON DEVE (MUST NOT) inviare un frame PUSH_PROMISE o un frame CANCEL_PUSH con un ID push maggiore dell'ID push massimo che il client ha fornito per la connessione. I client DEVONO (MUST) trattare un tentativo di farlo come un errore di connessione di tipo H3_ID_ERROR.
Una volta che un flusso push è stato aperto o riservato da un frame PUSH_PROMISE, il flusso push può essere utilizzato finché il client non ha annullato il push. Una volta che un client riceve un frame CANCEL_PUSH dal flusso di controllo o una terminazione del flusso dal flusso push, il push viene annullato. Se il flusso push termina senza un CANCEL_PUSH, il push è comunque considerato completato con successo.
I client possono interrompere un push inviando un frame CANCEL_PUSH. Dopo che il server lo ha ricevuto, il server DEVE (MUST) interrompere l'invio del push se il push non è ancora completo. I client possono anche interrompere un push reimpostando il flusso push. In entrambi i casi, il destinatario può scartare in sicurezza qualsiasi stato di risposta push ricevuto.
Una volta che un flusso di richiesta si chiude, le implementazioni possono scegliere di bufferizzare solo un riferimento alla risposta push o di rimuovere completamente il riferimento alla risposta push. Se viene ricevuta una risposta push con un flusso di richiesta associato chiuso, ciò non indica un fallimento del push.
I flussi push sono sempre referenziati da un ID push. Il destinatario di un frame PUSH_PROMISE associa l'ID push a un flusso avviato dal client, e un client che riceve un frame HEADERS su un flusso push associa l'ID push a un push ricevuto.
4.6.1. ID push (Push IDs)
Gli ID push sono interi senza segno a 62 bit (vedere la sezione 16 di [QUIC-TRANSPORT]) utilizzati per identificare un push del server. Gli ID push sono univoci per la durata della connessione.
Lo spazio degli ID push inizia da zero ed è un sottoinsieme dello spazio intero; pertanto, gli ID push non possono apparire in contesti che richiedono un ID flusso o un ID richiesta. In particolare, agli ID push non è consentito apparire nei frame GOAWAY (vedere la sezione 5.2).
Gli ID push vengono utilizzati in un singolo frame PUSH_PROMISE (vedere la sezione 7.2.5) e in un singolo flusso push (vedere le sezioni 4.6 e 6.2.2). Questi usi DEVONO (MUST) fare riferimento allo stesso push promesso effettuato dal server durante la durata della connessione.
Dopo aver inviato una risposta push su un flusso push, l'ID push non può essere riutilizzato. Se un client riceve un altro header di flusso push o un altro PUSH_PROMISE sullo stesso ID push da flussi diversi, questo DEVE (MUST) essere trattato come un errore di connessione di tipo H3_ID_ERROR.