RFC 9114 - HTTP/3
- Stato: Proposed Standard
- Pubblicato: June 2022
- Stream: IETF
- Errata: Nessun errata
Sommario (Abstract)
Il protocollo di trasporto QUIC (QUIC Transport Protocol) possiede diverse caratteristiche desiderabili per un trasporto HTTP, come il multiplexing dei flussi (Stream Multiplexing), il controllo di flusso per stream (Per-Stream Flow Control) e l'instaurazione di connessione a bassa latenza (Low-Latency Connection Establishment). Questo documento descrive una mappatura della semantica HTTP su QUIC. Questo documento identifica anche le funzionalità HTTP/2 che sono inglobate da QUIC e descrive come le estensioni HTTP/2 possono essere portate su HTTP/3.
Stato di questo Memo (Status of This Memo)
Questo è un documento Standards Track di Internet.
Questo documento è un prodotto dell'Internet Engineering Task Force (IETF). Rappresenta il consenso della comunità IETF. Ha ricevuto una revisione pubblica ed è stato approvato per la pubblicazione dall'Internet Engineering Steering Group (IESG). Ulteriori informazioni sugli Standard Internet sono disponibili nella Sezione 2 di RFC 7841.
Le informazioni sullo stato attuale di questo documento, eventuali errata e su come fornire feedback possono essere ottenute all'indirizzo https://www.rfc-editor.org/info/rfc9114.
Indice (Table of Contents)
Capitoli principali
- 1. Introduction (Introduzione)
- 2. HTTP/3 Protocol Overview (Panoramica del protocollo HTTP/3)
- 3. Connection Setup and Management (Configurazione e gestione della connessione)
- 4. Expressing HTTP Semantics in HTTP/3 (Espressione della semantica HTTP in HTTP/3)
- 5. Connection Closure (Chiusura della connessione)
- 6. Stream Mapping and Usage (Mappatura e utilizzo dei flussi)
- 7. HTTP Framing Layer (Livello di framing HTTP)
- 8. Error Handling (Gestione degli errori)
- 9. Extensions to HTTP/3 (Estensioni a HTTP/3)
- 10. Security Considerations (Considerazioni sulla sicurezza)
- 11. IANA Considerations (Considerazioni IANA)
- 12. References (Riferimenti)
Appendici
Risorse correlate
- Testo ufficiale: RFC 9114
- Pagina ufficiale: RFC 9114 DataTracker
- Errata: RFC Editor Errata
1. Introduction (Introduzione)
La semantica HTTP (HTTP Semantics) ([HTTP]) viene utilizzata per un'ampia gamma di servizi su Internet. Questa semantica è stata utilizzata più comunemente con HTTP/1.1 e HTTP/2. HTTP/1.1 è stato utilizzato su una varietà di livelli di trasporto e sessione, mentre HTTP/2 è stato utilizzato principalmente con TLS su TCP. HTTP/3 supporta la stessa semantica su un nuovo protocollo di trasporto: QUIC.
1.1. Prior Versions of HTTP (Versioni precedenti di HTTP)
HTTP/1.1 ([HTTP/1.1]) utilizza campi di testo delimitati da spazi per trasmettere i messaggi HTTP. Sebbene questi scambi siano leggibili dall'uomo, l'uso di spazi per la formattazione dei messaggi porta a complessità di analisi e tolleranza eccessiva di comportamenti varianti.
Poiché HTTP/1.1 non include un livello di multiplexing (Multiplexing Layer), vengono spesso utilizzate più connessioni TCP per gestire le richieste in parallelo. Tuttavia, ciò ha un impatto negativo sul controllo della congestione (Congestion Control) e sull'efficienza della rete, poiché TCP non condivide il controllo della congestione tra più connessioni.
HTTP/2 ([HTTP/2]) ha introdotto un livello di framing binario (Binary Framing) e di multiplexing per migliorare la latenza senza modificare il livello di trasporto. Tuttavia, poiché la natura parallela del multiplexing di HTTP/2 non è visibile ai meccanismi di recupero delle perdite (Loss Recovery Mechanisms) di TCP, un pacchetto perso o riordinato causa uno stallo (Stall) di tutte le transazioni attive, indipendentemente dal fatto che quella transazione sia stata direttamente impattata dal pacchetto perso.
1.2. Delegation to QUIC (Delega a QUIC)
Il protocollo di trasporto QUIC (QUIC Transport Protocol) incorpora il multiplexing dei flussi (Stream Multiplexing) e il controllo di flusso per stream (Per-Stream Flow Control), simile a quello fornito dal livello di framing HTTP/2. Fornendo affidabilità (Reliability) a livello di stream e controllo della congestione su tutta la connessione, QUIC ha la capacità di migliorare le prestazioni di HTTP rispetto a una mappatura TCP. QUIC incorpora anche TLS 1.3 ([TLS]) a livello di trasporto, offrendo riservatezza (Confidentiality) e integrità (Integrity) comparabili all'esecuzione di TLS su TCP, con la latenza di configurazione della connessione migliorata di TCP Fast Open ([TFO]).
Questo documento definisce HTTP/3: una mappatura della semantica HTTP sul protocollo di trasporto QUIC, attingendo pesantemente al design di HTTP/2. HTTP/3 si basa su QUIC per fornire protezione della riservatezza e dell'integrità dei dati, autenticazione peer (Peer Authentication) e consegna affidabile, ordinata e per stream. Delegando i problemi di durata del flusso (Stream Lifetime) e di controllo di flusso a QUIC, viene utilizzato un framing binario simile al framing HTTP/2 su ciascun stream. Alcune funzionalità HTTP/2 sono sussume da QUIC, mentre altre funzionalità sono implementate su QUIC.
QUIC è descritto in [QUIC-TRANSPORT]. Per una descrizione completa di HTTP/2, vedere [HTTP/2].
2. HTTP/3 Protocol Overview (Panoramica del protocollo HTTP/3)
HTTP/3 fornisce un trasporto per la semantica HTTP utilizzando il protocollo di trasporto QUIC (QUIC Transport Protocol) e un livello di framing interno (Framing Layer) simile a HTTP/2.
Una volta che un client sa che esiste un server HTTP/3 in un determinato endpoint, apre una connessione QUIC. QUIC fornisce negoziazione del protocollo (Protocol Negotiation), multiplexing basato su stream (Stream-Based Multiplexing) e controllo di flusso (Flow Control). La scoperta di un endpoint HTTP/3 è descritta nella sezione 3.1.
All'interno di ogni stream, l'unità di base della comunicazione HTTP/3 è un frame (sezione 7.2). Ogni tipo di frame ha uno scopo diverso. Ad esempio, i frame HEADERS e DATA formano la base delle richieste e risposte HTTP (sezione 4.1). I frame che si applicano all'intera connessione vengono trasmessi su uno stream di controllo dedicato (Control Stream).
Il multiplexing delle richieste viene eseguito utilizzando l'astrazione di stream QUIC (Stream Abstraction), descritta nella sezione 2 di [QUIC-TRANSPORT]. Ogni coppia richiesta-risposta consuma un singolo stream QUIC. Gli stream sono indipendenti l'uno dall'altro, quindi uno stream bloccato o che subisce perdita di pacchetti non impedisce il progresso su altri stream.
Il push del server (Server Push) è una modalità di interazione introdotta in HTTP/2 ([HTTP/2]) che consente a un server di inviare uno scambio richiesta-risposta a un client in previsione della richiesta indicata dal client. Questo scambia l'utilizzo della rete contro un potenziale guadagno di latenza. Diversi frame HTTP/3 vengono utilizzati per gestire il push del server, come PUSH_PROMISE, MAX_PUSH_ID e CANCEL_PUSH.
Come in HTTP/2, i campi di richiesta e risposta (Fields) vengono compressi per la trasmissione. Poiché HPACK ([HPACK]) si basa sulla trasmissione ordinata di sezioni di campi compressi (Field Sections) (una garanzia non fornita da QUIC), HTTP/3 sostituisce HPACK con QPACK ([QPACK]). QPACK utilizza stream unidirezionali separati per modificare e tracciare lo stato della tabella dei campi (Field Table State), mentre le sezioni di campi codificate fanno riferimento allo stato della tabella senza modificarlo.
2.1. Document Organization (Organizzazione del documento)
Le sezioni seguenti forniscono una panoramica dettagliata del ciclo di vita di una connessione HTTP/3:
-
"Connection Setup and Management" (Configurazione e gestione della connessione) (sezione 3) copre come viene scoperto un endpoint HTTP/3 e come viene stabilita una connessione HTTP/3.
-
"Expressing HTTP Semantics in HTTP/3" (Espressione della semantica HTTP in HTTP/3) (sezione 4) descrive come la semantica HTTP viene espressa utilizzando i frame.
-
"Connection Closure" (Chiusura della connessione) (sezione 5) descrive come le connessioni HTTP/3 vengono terminate, sia in modo graduale che brusco.
I dettagli del protocollo wire (Wire Protocol) e le interazioni con il trasporto sono descritti nelle sezioni successive:
-
"Stream Mapping and Usage" (Mappatura e utilizzo dei flussi) (sezione 6) descrive il modo in cui vengono utilizzati gli stream QUIC.
-
"HTTP Framing Layer" (Livello di framing HTTP) (sezione 7) descrive i frame utilizzati sulla maggior parte degli stream.
-
"Error Handling" (Gestione degli errori) (sezione 8) descrive come le condizioni di errore vengono gestite ed espresse, sia su un particolare stream che per la connessione nel suo insieme.
Risorse aggiuntive sono fornite nelle sezioni finali:
-
"Extensions to HTTP/3" (Estensioni a HTTP/3) (sezione 9) descrive come nuove capacità possono essere aggiunte in documenti futuri.
-
Un confronto più dettagliato tra HTTP/2 e HTTP/3 può essere trovato nell'appendice A.
2.2. Conventions and Terminology (Convenzioni e terminologia)
Le parole chiave "MUST" (deve), "MUST NOT" (non deve), "REQUIRED" (richiesto), "SHALL" (deve), "SHALL NOT" (non deve), "SHOULD" (dovrebbe), "SHOULD NOT" (non dovrebbe), "RECOMMENDED" (raccomandato), "NOT RECOMMENDED" (non raccomandato), "MAY" (può) e "OPTIONAL" (opzionale) in questo documento devono essere interpretate come descritto in BCP 14 [RFC2119] [RFC8174] quando, e solo quando, appaiono in maiuscolo, come mostrato qui.
Questo documento utilizza la codifica di interi a lunghezza variabile (Variable-Length Integer Encoding) da [QUIC-TRANSPORT].
Vengono utilizzati i seguenti termini:
abort (interruzione): Una terminazione brusca di una connessione o di uno stream, possibilmente dovuta a una condizione di errore.
client: L'endpoint che avvia una connessione HTTP/3. I client inviano richieste HTTP e ricevono risposte HTTP.
connection (connessione): Una connessione a livello di trasporto tra due endpoint che utilizzano QUIC come protocollo di trasporto.
connection error (errore di connessione): Un errore che influisce sull'intera connessione HTTP/3.
endpoint: Il client o il server della connessione.
frame: L'unità più piccola di comunicazione su uno stream in HTTP/3, costituita da un'intestazione e una sequenza di byte a lunghezza variabile strutturata secondo il tipo di frame.
Elementi di protocollo chiamati "frame" esistono sia in questo documento che in [QUIC-TRANSPORT]. Quando si fa riferimento ai frame di [QUIC-TRANSPORT], il nome del frame sarà preceduto da "QUIC". Ad esempio, "QUIC CONNECTION_CLOSE frames". I riferimenti senza questo prefisso si riferiscono ai frame definiti nella sezione 7.2.
HTTP/3 connection (connessione HTTP/3): Una connessione QUIC in cui il protocollo applicativo negoziato è HTTP/3.
peer: Un endpoint. Quando si discute di un particolare endpoint, "peer" si riferisce all'endpoint remoto rispetto al soggetto principale della discussione.
receiver (ricevitore): Un endpoint che sta ricevendo frame.
sender (mittente): Un endpoint che sta trasmettendo frame.
server: L'endpoint che accetta una connessione HTTP/3. I server ricevono richieste HTTP e inviano risposte HTTP.
stream (flusso): Un flusso di byte bidirezionale o unidirezionale (Bytestream) fornito dal trasporto QUIC. Tutti gli stream all'interno di una connessione HTTP/3 possono essere considerati "stream HTTP/3", ma all'interno di HTTP/3 sono definiti più tipi di stream.
stream error (errore di stream): Un errore a livello di applicazione sullo stream individuale.
Il termine "content" (contenuto) è definito nella sezione 6.4 di [HTTP].
Infine, i termini "resource" (risorsa), "message" (messaggio), "user agent" (agente utente), "origin server" (server di origine), "gateway", "intermediary" (intermediario), "proxy" e "tunnel" sono definiti nella sezione 3 di [HTTP].
I diagrammi di pacchetto (Packet Diagrams) in questo documento utilizzano il formato definito nella sezione 1.3 di [QUIC-TRANSPORT] per illustrare l'ordine e la dimensione dei campi.
3. Connection Setup and Management (Configurazione e gestione della connessione)
3.1. Discovering an HTTP/3 Endpoint (Scoperta di un endpoint HTTP/3)
HTTP si basa sulla nozione di risposta autoritativa (Authoritative Response): una risposta che è stata determinata essere la risposta più appropriata per quella richiesta, dato lo stato della risorsa di destinazione al momento dell'origine del messaggio di risposta da parte (o su indicazione) del server di origine (Origin Server) identificato nell'URI di destinazione. La localizzazione di un server autoritativo per un URI HTTP è discussa nella sezione 4.3 di [HTTP].
Lo schema "https" associa l'autorità al possesso di un certificato che il client considera affidabile per l'host identificato dal componente di autorità (Authority Component) dell'URI. Alla ricezione di un certificato del server nell'handshake TLS, il client deve (MUST) verificare che il certificato sia una corrispondenza accettabile per il server di origine dell'URI utilizzando il processo descritto nella sezione 4.3.4 di [HTTP]. Se il certificato non può essere verificato rispetto al server di origine dell'URI, il client non deve (MUST NOT) considerare il server autoritativo per quell'origine.
Un client può (MAY) tentare l'accesso a una risorsa con un URI "https" risolvendo l'identificatore dell'host in un indirizzo IP, stabilendo una connessione QUIC a quell'indirizzo sulla porta indicata (inclusa la validazione del certificato del server come descritto sopra) e inviando un messaggio di richiesta HTTP/3 che punta all'URI al server su quella connessione sicura. A meno che non venga utilizzato qualche altro meccanismo per selezionare HTTP/3, il token "h3" viene utilizzato nell'estensione ALPN (Application-Layer Protocol Negotiation; vedere [RFC7301]) durante l'handshake TLS.
Problemi di connettività (ad esempio, blocco UDP) possono comportare un fallimento nello stabilire una connessione QUIC; i client dovrebbero (SHOULD) tentare di utilizzare versioni basate su TCP di HTTP in questo caso.
I server possono (MAY) servire HTTP/3 su qualsiasi porta UDP; un annuncio di servizio alternativo (Alternative Service Advertisement) include sempre una porta esplicita, e gli URI contengono una porta esplicita o una porta predefinita associata allo schema.
3.1.1. HTTP Alternative Services (Servizi alternativi HTTP)
Un'origine HTTP può annunciare la disponibilità di un endpoint HTTP/3 equivalente tramite il campo di intestazione della risposta HTTP Alt-Svc o il frame HTTP/2 ALTSVC ([ALTSVC]) utilizzando il token ALPN "h3".
Ad esempio, un'origine potrebbe indicare in una risposta HTTP che HTTP/3 era disponibile sulla porta UDP 50781 allo stesso nome host includendo il seguente campo di intestazione:
Alt-Svc: h3=":50781"
Alla ricezione di un record Alt-Svc che indica il supporto HTTP/3, un client può (MAY) tentare di stabilire una connessione QUIC all'host e alla porta indicati; se questa connessione ha successo, il client può inviare richieste HTTP utilizzando la mappatura descritta in questo documento.
3.1.2. Other Schemes (Altri schemi)
Sebbene HTTP sia indipendente dal protocollo di trasporto, lo schema "http" associa l'autorità con la capacità di ricevere connessioni TCP sulla porta indicata di qualsiasi host identificato all'interno del componente di autorità. Poiché HTTP/3 non utilizza TCP, HTTP/3 non può essere utilizzato per l'accesso diretto al server autoritativo per una risorsa identificata da un URI "http". Tuttavia, estensioni di protocollo come [ALTSVC] permettono al server autoritativo di identificare altri servizi che sono anche autoritativi e che potrebbero essere raggiungibili tramite HTTP/3.
Prima di effettuare richieste per un'origine il cui schema non è "https", il client deve (MUST) assicurarsi che il server sia disposto a servire quello schema. Per le origini il cui schema è "http", un metodo sperimentale per raggiungere questo obiettivo è descritto in [RFC8164]. Altri meccanismi potrebbero essere definiti per vari schemi in futuro.
3.2. Connection Establishment (Stabilimento della connessione)
HTTP/3 si basa su QUIC versione 1 come trasporto sottostante. L'uso di altre versioni di trasporto QUIC con HTTP/3 può (MAY) essere definito da specifiche future.
QUIC versione 1 utilizza TLS versione 1.3 o superiore come protocollo di handshake (Handshake Protocol). I client HTTP/3 devono (MUST) supportare un meccanismo per indicare l'host di destinazione al server durante l'handshake TLS. Se il server è identificato da un nome di dominio ([DNS-TERMS]), i client devono (MUST) inviare l'estensione TLS Server Name Indication (SNI; [RFC6066]) a meno che non venga utilizzato un meccanismo alternativo per indicare l'host di destinazione.
Le connessioni QUIC vengono stabilite come descritto in [QUIC-TRANSPORT]. Durante lo stabilimento della connessione, il supporto HTTP/3 è indicato selezionando il token ALPN "h3" nell'handshake TLS. Il supporto per altri protocolli a livello di applicazione può (MAY) essere offerto nello stesso handshake.
Mentre le opzioni a livello di connessione relative al protocollo QUIC principale vengono impostate nell'handshake crittografico iniziale, le impostazioni specifiche di HTTP/3 vengono trasmesse nel frame SETTINGS. Dopo che la connessione QUIC è stata stabilita, un frame SETTINGS deve (MUST) essere inviato da ciascun endpoint come frame iniziale del rispettivo flusso di controllo HTTP (HTTP Control Stream).
3.3. Connection Reuse (Riutilizzo della connessione)
Le connessioni HTTP/3 sono persistenti attraverso più richieste. Per le migliori prestazioni, ci si aspetta che i client non chiudano le connessioni fino a quando non viene determinato che non è necessaria ulteriore comunicazione con un server (ad esempio, quando un utente si allontana da una particolare pagina web) o fino a quando il server chiude la connessione.
Una volta che esiste una connessione a un endpoint del server, questa connessione può (MAY) essere riutilizzata per richieste con più componenti di autorità URI diversi. Per utilizzare una connessione esistente per una nuova origine, i client devono (MUST) validare il certificato presentato dal server per il nuovo server di origine utilizzando il processo descritto nella sezione 4.3.4 di [HTTP]. Ciò implica che i client dovranno conservare il certificato del server e qualsiasi informazione aggiuntiva necessaria per verificare quel certificato; i client che non lo fanno non saranno in grado di riutilizzare la connessione per origini aggiuntive.
Se il certificato non è accettabile rispetto alla nuova origine per qualsiasi motivo, la connessione non deve (MUST NOT) essere riutilizzata e dovrebbe (SHOULD) essere stabilita una nuova connessione per la nuova origine. Se il motivo per cui il certificato non può essere verificato potrebbe applicarsi ad altre origini già associate alla connessione, il client dovrebbe (SHOULD) rivalidare il certificato del server per quelle origini. Ad esempio, se la validazione di un certificato fallisce perché il certificato è scaduto o è stato revocato, questo potrebbe essere utilizzato per invalidare tutte le altre origini per le quali quel certificato è stato utilizzato per stabilire l'autorità.
I client non dovrebbero (SHOULD NOT) aprire più di una connessione HTTP/3 a un determinato indirizzo IP e porta UDP, dove l'indirizzo IP e la porta potrebbero essere derivati da un URI, un servizio alternativo selezionato ([ALTSVC]), un proxy configurato o la risoluzione del nome di uno qualsiasi di questi. Un client può (MAY) aprire più connessioni HTTP/3 allo stesso indirizzo IP e porta UDP utilizzando diverse configurazioni di trasporto o TLS ma dovrebbe (SHOULD) evitare di creare più connessioni con la stessa configurazione.
I server sono incoraggiati a mantenere aperte le connessioni HTTP/3 il più a lungo possibile ma sono autorizzati a terminare le connessioni inattive (Idle Connections) se necessario. Quando uno dei due endpoint sceglie di chiudere la connessione HTTP/3, l'endpoint che termina dovrebbe (SHOULD) prima inviare un frame GOAWAY (sezione 5.2) in modo che entrambi gli endpoint possano determinare in modo affidabile se i frame precedentemente inviati sono stati elaborati e completare o terminare con grazia qualsiasi attività rimanente necessaria.
Un server che non desidera che i client riutilizzino le connessioni HTTP/3 per una particolare origine può indicare che non è autoritativo per una richiesta inviando un codice di stato 421 (Misdirected Request, Richiesta indirizzata erroneamente) in risposta alla richiesta; vedere sezione 7.4 di [HTTP].
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.
5. Chiusura della connessione (Connection Closure)
Una volta stabilita, una connessione HTTP/3 può essere utilizzata per molte richieste e risposte nel tempo fino a quando la connessione viene chiusa. La chiusura della connessione può avvenire in diversi modi.
5.1. Connessioni inattive (Idle Connections)
Ogni endpoint QUIC dichiara un timeout di inattività (Idle Timeout) durante l'handshake. Se la connessione QUIC rimane inattiva (nessun pacchetto ricevuto) per più di questa durata, il peer assumerà che la connessione sia stata chiusa. Le implementazioni HTTP/3 dovranno aprire una nuova connessione HTTP/3 per nuove richieste se la connessione esistente è rimasta inattiva per più del timeout di inattività negoziato durante l'handshake QUIC, e DOVREBBERO (SHOULD) farlo se si avvicinano al timeout di inattività; vedere la sezione 10.1 di [QUIC-TRANSPORT].
Ci si aspetta che i client HTTP richiedano che il trasporto mantenga le connessioni aperte mentre ci sono risposte in sospeso per richieste o push del server, come descritto nella sezione 10.1.2 di [QUIC-TRANSPORT]. Se il client non si aspetta una risposta dal server, è preferibile consentire a una connessione inattiva di scadere piuttosto che spendere sforzi per mantenere una connessione che potrebbe non essere necessaria. Un gateway PUÒ (MAY) mantenere le connessioni in previsione della necessità piuttosto che sostenere il costo di latenza della creazione della connessione ai server. I server NON DOVREBBERO (SHOULD NOT) mantenere attivamente le connessioni aperte.
5.2. Arresto della connessione (Connection Shutdown)
Anche quando una connessione non è inattiva, entrambi gli endpoint possono decidere di interrompere l'utilizzo della connessione e avviare una chiusura della connessione graziosa (Graceful Connection Close). Gli endpoint avviano l'arresto grazioso di una connessione HTTP/3 inviando un frame GOAWAY. Il frame GOAWAY contiene un identificatore che indica al ricevitore l'intervallo di richieste o push che sono stati o potrebbero essere elaborati in questa connessione. Il server invia un ID di flusso bidirezionale avviato dal client; il client invia un ID push. Le richieste o i push con l'identificatore indicato o superiore vengono rifiutati (sezione 4.1.1) dal mittente del GOAWAY. Questo identificatore PUÒ (MAY) essere zero se non sono state elaborate richieste o push.
Le informazioni nel frame GOAWAY consentono a un client e a un server di concordare quali richieste o push sono stati accettati prima dell'arresto della connessione HTTP/3. All'invio di un frame GOAWAY, l'endpoint DOVREBBE (SHOULD) annullare esplicitamente (vedere le sezioni 4.1.1 e 7.2.3) qualsiasi richiesta o push che abbia identificatori maggiori o uguali a quello indicato, al fine di ripulire lo stato di trasporto per i flussi interessati. L'endpoint DOVREBBE (SHOULD) continuare a farlo man mano che arrivano più richieste o push.
Gli endpoint NON DEVONO (MUST NOT) avviare nuove richieste o promettere nuovi push sulla connessione dopo la ricezione di un frame GOAWAY dal peer. I client POSSONO (MAY) stabilire una nuova connessione per inviare richieste aggiuntive.
Alcune richieste o push potrebbero essere già in transito:
-
Alla ricezione di un frame GOAWAY, se il client ha già inviato richieste con un ID di flusso maggiore o uguale all'identificatore contenuto nel frame GOAWAY, tali richieste non verranno elaborate. I client possono riprovare in modo sicuro le richieste non elaborate su una connessione HTTP diversa. Un client che non è in grado di riprovare le richieste perde tutte le richieste in transito quando il server chiude la connessione.
Le richieste su ID di flusso inferiori all'ID di flusso in un frame GOAWAY dal server potrebbero essere state elaborate; il loro stato non può essere conosciuto fino a quando non viene ricevuta una risposta, il flusso viene reimpostato individualmente, viene ricevuto un altro GOAWAY con un ID di flusso inferiore a quello della richiesta in questione, o la connessione termina.
I server POSSONO (MAY) rifiutare richieste individuali su flussi al di sotto dell'ID indicato se queste richieste non sono state elaborate.
-
Se un server riceve un frame GOAWAY dopo aver promesso push con un ID push maggiore o uguale all'identificatore contenuto nel frame GOAWAY, quei push non verranno accettati.
I server DOVREBBERO (SHOULD) inviare un frame GOAWAY quando la chiusura di una connessione è nota in anticipo, anche se il preavviso è breve, in modo che il peer remoto possa sapere se una richiesta è stata parzialmente elaborata o meno. Ad esempio, se un client HTTP invia un POST nello stesso momento in cui un server chiude una connessione QUIC, il client non può sapere se il server ha iniziato a elaborare quella richiesta POST se il server non invia un frame GOAWAY per indicare su quali flussi potrebbe aver agito.
Un endpoint PUÒ (MAY) inviare più frame GOAWAY indicando identificatori diversi, ma l'identificatore in ciascun frame NON DEVE (MUST NOT) essere maggiore dell'identificatore in qualsiasi frame precedente, poiché i client potrebbero aver già riprovato richieste non elaborate su un'altra connessione HTTP. Ricevere un GOAWAY contenente un identificatore maggiore di quello ricevuto in precedenza DEVE (MUST) essere trattato come un errore di connessione di tipo H3_ID_ERROR.
Un endpoint che sta tentando di arrestare graziosamente una connessione può inviare un frame GOAWAY con un valore impostato sul valore massimo possibile (2^62-4 per i server, 2^62-1 per i client). Ciò garantisce che il peer interrompa la creazione di nuove richieste o push. Dopo aver concesso il tempo per l'arrivo di eventuali richieste o push in transito, l'endpoint può inviare un altro frame GOAWAY indicando quali richieste o push potrebbe accettare prima della fine della connessione. Ciò garantisce che una connessione possa essere chiusa in modo pulito senza perdere richieste.
Un client ha maggiore flessibilità nel valore che sceglie per il campo Push ID in un GOAWAY che invia. Un valore di 2^62-1 indica che il server può continuare a soddisfare i push che sono già stati promessi. Un valore più piccolo indica che il client rifiuterà i push con ID push maggiori o uguali a questo valore. Come il server, il client PUÒ (MAY) inviare frame GOAWAY successivi purché l'ID push specificato non sia maggiore di qualsiasi valore inviato in precedenza.
Anche quando un GOAWAY indica che una determinata richiesta o push non verrà elaborato o accettato alla ricezione, le risorse di trasporto sottostanti esistono ancora. L'endpoint che ha avviato queste richieste può annullarle per ripulire lo stato di trasporto.
Una volta che tutte le richieste e i push accettati sono stati elaborati, l'endpoint può consentire alla connessione di diventare inattiva, oppure PUÒ (MAY) avviare una chiusura immediata della connessione. Un endpoint che completa un arresto grazioso DOVREBBE (SHOULD) utilizzare il codice di errore H3_NO_ERROR durante la chiusura della connessione.
Se un client ha consumato tutti gli ID di flusso bidirezionali disponibili con le richieste, il server non ha bisogno di inviare un frame GOAWAY, poiché il client non è in grado di effettuare ulteriori richieste.
5.3. Chiusura immediata dell'applicazione (Immediate Application Closure)
Un'implementazione HTTP/3 può chiudere immediatamente la connessione QUIC in qualsiasi momento. Ciò comporta l'invio di un frame QUIC CONNECTION_CLOSE al peer indicando che il livello applicazione ha terminato la connessione. Il codice di errore dell'applicazione in questo frame indica al peer perché la connessione viene chiusa. Vedere la sezione 8 per i codici di errore che possono essere utilizzati durante la chiusura di una connessione in HTTP/3.
Prima di chiudere la connessione, PUÒ (MAY) essere inviato un frame GOAWAY per consentire al client di riprovare alcune richieste. Includere il frame GOAWAY nello stesso pacchetto del frame QUIC CONNECTION_CLOSE migliora le possibilità che il frame venga ricevuto dai client.
Se ci sono flussi aperti che non sono stati esplicitamente chiusi, vengono chiusi implicitamente quando la connessione viene chiusa; vedere la sezione 10.2 di [QUIC-TRANSPORT].
5.4. Chiusura del trasporto (Transport Closure)
Per vari motivi, il trasporto QUIC potrebbe indicare al livello applicazione che la connessione è terminata. Ciò potrebbe essere dovuto a una chiusura esplicita da parte del peer, a un errore a livello di trasporto o a un cambiamento nella topologia di rete che interrompe la connettività.
Se una connessione termina senza un frame GOAWAY, i client DEVONO (MUST) presumere che qualsiasi richiesta inviata, in tutto o in parte, possa essere stata elaborata.
6. Mappatura e utilizzo dei flussi (Stream Mapping and Usage)
Un flusso QUIC fornisce la consegna affidabile e ordinata di byte, ma non garantisce l'ordine di consegna rispetto ai byte su altri flussi. Nella versione 1 di QUIC, i dati del flusso contenenti frame HTTP sono trasportati da frame QUIC STREAM, ma questo framing è invisibile al livello di framing HTTP. Il livello di trasporto bufferizza e ordina i dati del flusso ricevuti, esponendo un flusso di byte affidabile all'applicazione. Sebbene QUIC permetta la consegna fuori ordine all'interno di un flusso, HTTP/3 non utilizza questa funzionalità.
I flussi QUIC possono essere unidirezionali, trasportando dati solo dall'iniziatore al ricevitore, o bidirezionali, trasportando dati in entrambe le direzioni. I flussi possono essere avviati dal client o dal server. Per maggiori dettagli sui flussi QUIC, vedere la sezione 2 di [QUIC-TRANSPORT].
Quando i campi e i dati HTTP vengono inviati su QUIC, il livello QUIC gestisce la maggior parte della gestione dei flussi. HTTP non ha bisogno di effettuare alcun multiplexing separato quando utilizza QUIC: i dati inviati su un flusso QUIC vengono sempre mappati a una particolare transazione HTTP o all'intero contesto di connessione HTTP/3.
6.1. Flussi bidirezionali (Bidirectional Streams)
Tutti i flussi bidirezionali avviati dal client vengono utilizzati per richieste e risposte HTTP. Un flusso bidirezionale garantisce che la risposta possa essere facilmente correlata alla richiesta. Questi flussi sono chiamati flussi di richiesta (Request Streams).
Ciò significa che la prima richiesta del client si verifica sul flusso QUIC 0, con le richieste successive sui flussi 4, 8 e così via. Per consentire l'apertura di questi flussi, un server HTTP/3 DOVREBBE (SHOULD) configurare valori minimi non nulli per il numero di flussi consentiti e la finestra di controllo del flusso iniziale. Per non limitare inutilmente il parallelismo, almeno 100 flussi di richiesta DOVREBBERO (SHOULD) essere consentiti contemporaneamente.
HTTP/3 non utilizza flussi bidirezionali avviati dal server, sebbene un'estensione potrebbe definire un uso per questi flussi. I client DEVONO (MUST) trattare la ricezione di un flusso bidirezionale avviato dal server come un errore di connessione di tipo H3_STREAM_CREATION_ERROR a meno che tale estensione non sia stata negoziata.
6.2. Flussi unidirezionali (Unidirectional Streams)
I flussi unidirezionali, in entrambe le direzioni, vengono utilizzati per una serie di scopi. Lo scopo è indicato da un tipo di flusso (Stream Type), che viene inviato come intero a lunghezza variabile all'inizio del flusso. Il formato e la struttura dei dati che seguono questo intero sono determinati dal tipo di flusso.
Unidirectional Stream Header {
Stream Type (i),
}
Figura 1: Intestazione del flusso unidirezionale
In questo documento sono definiti due tipi di flusso: flussi di controllo (Control Streams) (sezione 6.2.1) e flussi push (Push Streams) (sezione 6.2.2). [QPACK] definisce due tipi di flusso aggiuntivi. Altri tipi di flusso possono essere definiti da estensioni a HTTP/3; vedere la sezione 9 per maggiori dettagli. Alcuni tipi di flusso sono riservati (sezione 6.2.3).
Le prestazioni delle connessioni HTTP/3 nella fase iniziale della loro vita sono sensibili alla creazione e allo scambio di dati su flussi unidirezionali. Gli endpoint che limitano eccessivamente il numero di flussi o la finestra di controllo del flusso di questi flussi aumenteranno la possibilità che il peer remoto raggiunga il limite presto e diventi bloccato. In particolare, le implementazioni dovrebbero considerare che i peer remoti potrebbero voler esercitare il comportamento del flusso riservato (sezione 6.2.3) con alcuni dei flussi unidirezionali che sono autorizzati a utilizzare.
Ogni endpoint deve creare almeno un flusso unidirezionale per il flusso di controllo HTTP. QPACK richiede due flussi unidirezionali aggiuntivi e altre estensioni potrebbero richiedere ulteriori flussi. Pertanto, i parametri di trasporto inviati sia dai client che dai server DEVONO (MUST) consentire al peer di creare almeno tre flussi unidirezionali. Questi parametri di trasporto DOVREBBERO (SHOULD) anche fornire almeno 1.024 byte di credito di controllo del flusso a ciascun flusso unidirezionale.
Si noti che un endpoint non è tenuto a concedere crediti aggiuntivi per creare più flussi unidirezionali se il suo peer consuma tutti i crediti iniziali prima di creare i flussi unidirezionali critici. Gli endpoint DOVREBBERO (SHOULD) creare il flusso di controllo HTTP e i flussi unidirezionali richiesti dalle estensioni obbligatorie (come i flussi encoder e decoder QPACK) per primi, e quindi creare flussi aggiuntivi come consentito dal loro peer.
Se l'intestazione del flusso indica un tipo di flusso che non è supportato dal destinatario, il resto del flusso non può essere consumato poiché la semantica è sconosciuta. I destinatari di tipi di flusso sconosciuti DEVONO (MUST) interrompere la lettura del flusso o scartare i dati in arrivo senza ulteriore elaborazione. Se la lettura viene interrotta, il destinatario DOVREBBE (SHOULD) utilizzare il codice di errore H3_STREAM_CREATION_ERROR o un codice di errore riservato (sezione 8.1). Il destinatario NON DEVE (MUST NOT) considerare i tipi di flusso sconosciuti come un errore di connessione di alcun tipo.
Poiché alcuni tipi di flusso possono influenzare lo stato della connessione, un destinatario NON DOVREBBE (SHOULD NOT) scartare i dati dai flussi unidirezionali in arrivo prima di leggere il tipo di flusso.
Le implementazioni POSSONO (MAY) inviare tipi di flusso prima di sapere se il peer li supporta. Tuttavia, i tipi di flusso che potrebbero modificare lo stato o la semantica dei componenti di protocollo esistenti, inclusi QPACK o altre estensioni, NON DEVONO (MUST NOT) essere inviati finché non è noto che il peer li supporta.
Un mittente può chiudere o reimpostare un flusso unidirezionale salvo diversa indicazione. Un ricevitore DEVE (MUST) tollerare che i flussi unidirezionali vengano chiusi o reimpostati prima della ricezione dell'intestazione del flusso unidirezionale.
6.2.1. Flussi di controllo (Control Streams)
Un flusso di controllo è indicato da un tipo di flusso di 0x00. I dati su questo flusso sono costituiti da frame HTTP/3, come definito nella sezione 7.2.
Ciascun lato DEVE (MUST) avviare un singolo flusso di controllo all'inizio della connessione e inviare il proprio frame SETTINGS come primo frame su questo flusso. Se il primo frame del flusso di controllo è qualsiasi altro tipo di frame, questo DEVE (MUST) essere trattato come un errore di connessione di tipo H3_MISSING_SETTINGS. È consentito un solo flusso di controllo per peer; la ricezione di un secondo flusso che dichiara di essere un flusso di controllo DEVE (MUST) essere trattata come un errore di connessione di tipo H3_STREAM_CREATION_ERROR. Il mittente NON DEVE (MUST NOT) chiudere il flusso di controllo e il ricevitore NON DEVE (MUST NOT) richiedere che il mittente chiuda il flusso di controllo. Se uno dei flussi di controllo viene chiuso in qualsiasi momento, questo DEVE (MUST) essere trattato come un errore di connessione di tipo H3_CLOSED_CRITICAL_STREAM. Gli errori di connessione sono descritti nella sezione 8.
Poiché i contenuti del flusso di controllo vengono utilizzati per gestire il comportamento di altri flussi, gli endpoint DOVREBBERO (SHOULD) fornire credito di controllo del flusso sufficiente per impedire che il flusso di controllo del peer diventi bloccato.
Viene utilizzata una coppia di flussi unidirezionali anziché un singolo flusso bidirezionale. Ciò consente a entrambi i peer di inviare dati non appena sono in grado. A seconda che 0-RTT sia disponibile sulla connessione QUIC, il client o il server potrebbero essere in grado di inviare prima i dati del flusso.
6.2.2. Flussi push (Push Streams)
Il push del server (Server Push) è una funzionalità opzionale introdotta in HTTP/2 che consente a un server di avviare una risposta prima che sia stata effettuata una richiesta. Vedere la sezione 4.6 per maggiori dettagli.
Un flusso push è indicato da un tipo di flusso di 0x01, seguito dall'ID push (Push ID) della promessa che soddisfa, codificato come intero a lunghezza variabile. I dati rimanenti su questo flusso sono costituiti da frame HTTP/3, come definito nella sezione 7.2, e soddisfano un push del server promesso da zero o più risposte HTTP provvisorie seguite da una singola risposta HTTP finale, come definito nella sezione 4.1. Il push del server e gli ID push sono descritti nella sezione 4.6.
Solo i server possono effettuare push; se un server riceve un flusso push avviato dal client, questo DEVE (MUST) essere trattato come un errore di connessione di tipo H3_STREAM_CREATION_ERROR.
Push Stream Header {
Stream Type (i) = 0x01,
Push ID (i),
}
Figura 2: Intestazione del flusso push
Un client NON DOVREBBE (SHOULD NOT) interrompere la lettura su un flusso push prima di leggere l'intestazione del flusso push, poiché ciò potrebbe portare a disaccordo tra client e server su quali ID push sono già stati consumati.
Ogni ID push DEVE (MUST) essere utilizzato solo una volta in un'intestazione del flusso push. Se un client rileva che un'intestazione del flusso push include un ID push che è stato utilizzato in un'altra intestazione del flusso push, il client DEVE (MUST) trattare questo come un errore di connessione di tipo H3_ID_ERROR.
6.2.3. Tipi di flusso riservati (Reserved Stream Types)
I tipi di flusso del formato 0x1f * N + 0x21 per valori interi non negativi di N sono riservati per esercitare il requisito che i tipi sconosciuti vengano ignorati. Questi flussi non hanno semantica e possono essere inviati quando è desiderato il padding a livello di applicazione. POSSONO (MAY) anche essere inviati su connessioni in cui non vengono attualmente trasferiti dati. Gli endpoint NON DEVONO (MUST NOT) considerare che questi flussi abbiano alcun significato alla ricezione.
Il payload e la lunghezza del flusso vengono selezionati in qualsiasi modo scelga l'implementazione mittente. Quando si invia un tipo di flusso riservato, l'implementazione PUÒ (MAY) terminare il flusso in modo pulito o reimpostarlo. Quando si reimposta il flusso, DOVREBBE (SHOULD) essere utilizzato il codice di errore H3_NO_ERROR o un codice di errore riservato (sezione 8.1).
7. Livello di framing HTTP (HTTP Framing Layer)
I frame HTTP sono trasportati sui flussi QUIC, come descritto nella Sezione 6. HTTP/3 definisce tre tipi di flusso: flusso di controllo, flusso di richiesta e flusso push. Questa sezione descrive i formati dei frame HTTP/3 e i loro tipi di flusso consentiti; vedere la Tabella 1 per una panoramica.
Tabella 1: Panoramica dei frame HTTP/3 e dei tipi di flusso
| Frame | Flusso di controllo | Flusso di richiesta | Flusso push | Sezione |
|---|---|---|---|---|
| DATA | No | Sì | Sì | 7.2.1 |
| HEADERS | No | Sì | Sì | 7.2.2 |
| CANCEL_PUSH | Sì | No | No | 7.2.3 |
| SETTINGS | Sì (1) | No | No | 7.2.4 |
| PUSH_PROMISE | No | Sì | No | 7.2.5 |
| GOAWAY | Sì | No | No | 7.2.6 |
| MAX_PUSH_ID | Sì | No | No | 7.2.7 |
| Riservato | Sì | Sì | Sì | 7.2.8 |
Il frame SETTINGS può verificarsi solo come primo frame di un flusso di controllo; questo è indicato nella Tabella 1 con (1).
Si noti che, a differenza dei frame QUIC, i frame HTTP/3 possono estendersi su più pacchetti.
7.1. Layout dei frame (Frame Layout)
Tutti i frame hanno il seguente formato:
HTTP/3 Frame Format {
Type (i),
Length (i),
Frame Payload (..),
}
Un frame include i seguenti campi:
- Type (Tipo): Un intero a lunghezza variabile che identifica il tipo di frame
- Length (Lunghezza): Un intero a lunghezza variabile che descrive la lunghezza in byte del payload del frame
- Frame Payload (Payload del frame): Un payload la cui semantica è determinata dal campo Type
Il payload di ogni frame DEVE (MUST) contenere esattamente i campi identificati nella sua descrizione. Un payload di frame che contiene byte aggiuntivi o termina prematuramente DEVE (MUST) essere trattato come un errore di connessione di tipo H3_FRAME_ERROR.
7.2. Definizioni dei frame (Frame Definitions)
7.2.1. DATA
I frame DATA (type=0x00) trasmettono sequenze di byte arbitrarie a lunghezza variabile associate al contenuto della richiesta o risposta HTTP.
I frame DATA DEVONO (MUST) essere associati a una richiesta o risposta HTTP. Se un frame DATA viene ricevuto su un flusso di controllo, il destinatario DEVE (MUST) rispondere con un errore di connessione di tipo H3_FRAME_UNEXPECTED.
7.2.2. HEADERS
Il frame HEADERS (type=0x01) viene utilizzato per trasportare una sezione di campo HTTP codificata utilizzando QPACK.
I frame HEADERS possono essere inviati solo sui flussi di richiesta o sui flussi push. Se un frame HEADERS viene ricevuto su un flusso di controllo, il destinatario DEVE (MUST) rispondere con un errore di connessione di tipo H3_FRAME_UNEXPECTED.
7.2.3. CANCEL_PUSH
Il frame CANCEL_PUSH (type=0x03) viene utilizzato per richiedere la cancellazione di un push del server prima della ricezione del flusso push.
Quando un client invia un frame CANCEL_PUSH, indica che non desidera ricevere la risorsa promessa. Il server DOVREBBE (SHOULD) interrompere l'invio della risorsa.
I frame CANCEL_PUSH vengono inviati sul flusso di controllo. La ricezione di un frame CANCEL_PUSH su un flusso di richiesta o flusso push DEVE (MUST) essere trattata come un errore di connessione di tipo H3_FRAME_UNEXPECTED.
7.2.4. SETTINGS
Il frame SETTINGS (type=0x04) trasmette parametri di configurazione che influenzano il modo in cui gli endpoint comunicano.
I frame SETTINGS DEVONO (MUST) essere inviati come primo frame di ogni flusso di controllo. I frame SETTINGS NON DEVONO (MUST NOT) essere inviati su altri flussi.
Gli identificatori di impostazione definiti includono:
- SETTINGS_MAX_FIELD_SECTION_SIZE (0x06): Dimensione massima della sezione di campo
- SETTINGS_QPACK_MAX_TABLE_CAPACITY (0x01): Impostazione relativa a QPACK
- SETTINGS_QPACK_BLOCKED_STREAMS (0x07): Impostazione relativa a QPACK
7.2.5. PUSH_PROMISE
Il frame PUSH_PROMISE (type=0x05) viene utilizzato per trasportare una sezione di campo di intestazione di richiesta promessa dal server al client su un flusso di richiesta.
I frame PUSH_PROMISE possono essere inviati solo sui flussi di richiesta. La ricezione di un frame PUSH_PROMISE su un flusso di controllo o flusso push DEVE (MUST) essere trattata come un errore di connessione di tipo H3_FRAME_UNEXPECTED.
7.2.6. GOAWAY
Il frame GOAWAY (type=0x07) viene utilizzato per avviare la chiusura graduale di una connessione.
I frame GOAWAY vengono sempre inviati sul flusso di controllo. La ricezione di un frame GOAWAY su un flusso di richiesta o flusso push DEVE (MUST) essere trattata come un errore di connessione di tipo H3_FRAME_UNEXPECTED.
7.2.7. MAX_PUSH_ID
Il frame MAX_PUSH_ID (type=0x0d) viene utilizzato dai client per controllare il numero di push del server che il server può avviare.
I frame MAX_PUSH_ID vengono sempre inviati sul flusso di controllo. Un server NON DEVE (MUST NOT) inviare un frame MAX_PUSH_ID.
7.2.8. Tipi di frame riservati (Reserved Frame Types)
I tipi di frame nel formato 0x1f * N + 0x21 per valori interi non negativi di N sono riservati per esercitare il requisito che i tipi sconosciuti vengano ignorati. Questi frame non hanno semantica e possono essere inviati su qualsiasi flusso.
8. Gestione degli errori (Error Handling)
Quando un flusso non può essere completato con successo, QUIC consente all'applicazione di terminare bruscamente (reimpostare) quel flusso e comunicare un motivo; vedere la Sezione 2.4 di [QUIC-TRANSPORT]. Questo è chiamato "errore di flusso (Stream Error)". Un'implementazione HTTP/3 può decidere di chiudere un flusso QUIC e comunicare il tipo di errore. Le codifiche su rete dei codici di errore sono definite nella Sezione 8.1. Gli errori di flusso sono distinti dai codici di stato HTTP che indicano condizioni di errore. Gli errori di flusso indicano che il mittente non ha trasferito o consumato la richiesta o risposta completa, mentre i codici di stato HTTP indicano il risultato di una richiesta ricevuta con successo.
Se è necessario terminare un'intera connessione, QUIC fornisce meccanismi simili per comunicare un motivo; vedere la Sezione 5.3 di [QUIC-TRANSPORT]. Questo è chiamato "errore di connessione (Connection Error)". Simile agli errori di flusso, un'implementazione HTTP/3 può terminare una connessione QUIC e comunicare il motivo utilizzando un codice di errore dalla Sezione 8.1.
Sebbene i motivi per chiudere flussi e connessioni siano chiamati "errori", queste azioni non indicano necessariamente un problema con la connessione o con una delle implementazioni. Ad esempio, un flusso può essere reimpostato se la risorsa richiesta non è più necessaria.
Un endpoint PUÒ (MAY) scegliere di trattare un errore di flusso come un errore di connessione in determinate circostanze, chiudendo l'intera connessione in risposta a una condizione su un singolo flusso. Le implementazioni devono considerare l'impatto sulle richieste in sospeso prima di fare questa scelta.
Poiché nuovi codici di errore possono essere definiti senza negoziazione (vedere la Sezione 9), l'uso di un codice di errore in un contesto imprevisto o la ricezione di un codice di errore sconosciuto DEVE (MUST) essere trattato come equivalente a H3_NO_ERROR. Tuttavia, la chiusura di un flusso può avere altri effetti indipendentemente dal codice di errore; ad esempio, vedere la Sezione 4.1.
8.1. Codici di errore HTTP/3 (HTTP/3 Error Codes)
I seguenti codici di errore sono definiti per l'uso quando si terminano bruscamente i flussi, si interrompe la lettura dei flussi o si chiudono immediatamente le connessioni HTTP/3.
H3_NO_ERROR (0x0100)
Nessun errore. Utilizzato quando la connessione o il flusso deve essere chiuso, ma non c'è alcun errore da segnalare.
H3_GENERAL_PROTOCOL_ERROR (0x0101)
Il peer ha violato i requisiti del protocollo in un modo che non corrisponde a un codice di errore più specifico o l'endpoint rifiuta di utilizzare il codice di errore più specifico.
H3_INTERNAL_ERROR (0x0102)
Si è verificato un errore interno nello stack HTTP.
H3_STREAM_CREATION_ERROR (0x0103)
L'endpoint ha rilevato che il suo peer ha creato un flusso che non accetterà.
H3_CLOSED_CRITICAL_STREAM (0x0104)
Un flusso richiesto dalla connessione HTTP/3 è stato chiuso o reimpostato.
H3_FRAME_UNEXPECTED (0x0105)
È stato ricevuto un frame che non era consentito nello stato corrente o sul flusso corrente.
H3_FRAME_ERROR (0x0106)
È stato ricevuto un frame che non soddisfa i requisiti di layout o con una dimensione non valida.
H3_EXCESSIVE_LOAD (0x0107)
L'endpoint ha rilevato che il suo peer sta mostrando un comportamento che potrebbe generare un carico eccessivo.
H3_ID_ERROR (0x0108)
Un ID di flusso o un ID push è stato utilizzato in modo errato, ad esempio superando un limite, riducendo un limite o venendo riutilizzato.
H3_SETTINGS_ERROR (0x0109)
Un endpoint ha rilevato un errore nel payload di un frame SETTINGS.
H3_MISSING_SETTINGS (0x010a)
Nessun frame SETTINGS è stato ricevuto all'inizio del flusso di controllo.
H3_REQUEST_REJECTED (0x010b)
Un server ha rifiutato una richiesta senza eseguire alcuna elaborazione dell'applicazione.
H3_REQUEST_CANCELLED (0x010c)
La richiesta o la sua risposta (inclusa la risposta push) è annullata.
H3_REQUEST_INCOMPLETE (0x010d)
Il flusso del client è terminato senza contenere una richiesta completamente formata.
H3_MESSAGE_ERROR (0x010e)
Un messaggio HTTP era malformato e non può essere elaborato.
H3_CONNECT_ERROR (0x010f)
La connessione TCP stabilita in risposta a una richiesta CONNECT è stata reimpostata o chiusa in modo anomalo.
H3_VERSION_FALLBACK (0x0110)
L'operazione richiesta non può essere servita tramite HTTP/3. Il peer dovrebbe riprovare tramite HTTP/1.1.
I codici di errore nel formato 0x1f * N + 0x21 per valori interi non negativi di N sono riservati per esercitare il requisito che i codici di errore sconosciuti vengano trattati come equivalenti a H3_NO_ERROR (Sezione 9). Le implementazioni DOVREBBERO (SHOULD) selezionare un codice di errore da questo spazio con una certa probabilità quando avrebbero inviato H3_NO_ERROR.
9. Estensioni a HTTP/3 (Extensions to HTTP/3)
HTTP/3 permette l'estensione del protocollo. Entro i limiti descritti in questa sezione, le estensioni di protocollo possono essere utilizzate per fornire servizi aggiuntivi o alterare qualsiasi aspetto del protocollo. Le estensioni sono effettive solo nell'ambito di una singola connessione HTTP/3.
Questo si applica agli elementi di protocollo definiti in questo documento. Questo non influisce sulle opzioni esistenti per estendere HTTP, come la definizione di nuovi metodi, codici di stato o campi.
Le estensioni possono utilizzare nuovi tipi di frame (Sezione 7.2), nuove impostazioni (Sezione 7.2.4.1), nuovi codici di errore (Sezione 8) o nuovi tipi di flusso unidirezionale (Sezione 6.2). Sono stabiliti registri per gestire questi punti di estensione: tipi di frame (Sezione 11.2.1), impostazioni (Sezione 11.2.2), codici di errore (Sezione 11.2.3) e tipi di flusso (Sezione 11.2.4).
Le implementazioni DEVONO (MUST) ignorare valori sconosciuti o non supportati in tutti gli elementi di protocollo estensibili. Le implementazioni DEVONO (MUST) scartare i dati o interrompere la lettura su flussi unidirezionali che hanno tipi sconosciuti o non supportati. Ciò significa che qualsiasi di questi punti di estensione può essere utilizzato in modo sicuro dalle estensioni senza accordo o negoziazione preventiva. Tuttavia, dove un tipo di frame noto deve trovarsi in una posizione specifica, come il frame SETTINGS come primo frame del flusso di controllo (vedere Sezione 6.2.1), un tipo di frame sconosciuto non soddisfa tale requisito e DOVREBBE (SHOULD) essere trattato come un errore.
Le estensioni che potrebbero modificare la semantica dei componenti di protocollo esistenti DEVONO (MUST) essere negoziate prima di essere utilizzate. Ad esempio, un'estensione che modifica il layout del frame HEADERS non può essere utilizzata fino a quando il peer non ha dato un segnale positivo che questo è accettabile. Coordinare quando tale layout rivisto entra in vigore potrebbe rivelarsi complesso. In quanto tale, l'allocazione di nuovi identificatori per nuove definizioni di elementi di protocollo esistenti è probabilmente più efficace.
Questo documento non impone un metodo specifico per negoziare l'uso di un'estensione, ma nota che un'impostazione (Sezione 7.2.4.1) potrebbe essere utilizzata a tale scopo. Se entrambi i peer impostano un valore che indica la volontà di utilizzare l'estensione, allora l'estensione può essere utilizzata. Se un'impostazione viene utilizzata per la negoziazione dell'estensione, il valore predefinito DEVE (MUST) essere definito in modo tale che l'estensione sia disabilitata se l'impostazione viene omessa.
10. Considerazioni sulla sicurezza
Le considerazioni di sicurezza per HTTP/3 dovrebbero essere paragonabili a quelle di HTTP/2 con TLS. Tuttavia, molte delle considerazioni della Sezione 10 di [HTTP/2] si applicano a [QUIC-TRANSPORT] e sono discusse in quel documento.
10.1. Autorità del server
HTTP/3 si basa sulla definizione di autorità di HTTP. Le considerazioni sulla sicurezza per stabilire l'autorità sono trattate nella Sezione 17.1 di [HTTP].
10.2. Attacchi tra protocolli
L'uso di ALPN nell'handshake TLS e QUIC stabilisce il protocollo applicativo previsto prima dell'elaborazione dei byte del livello applicativo. Questo fornisce agli endpoint una forte garanzia che il pari stia usando lo stesso protocollo.
Ciò non garantisce la prevenzione di tutti gli attacchi tra protocolli. La Sezione 21.5 di [QUIC-TRANSPORT] descrive alcuni modi in cui il testo in chiaro dei pacchetti QUIC può essere usato per eseguire falsificazioni di richieste contro endpoint che non usano un trasporto autenticato.
10.3. Attacchi di incapsulamento tramite intermediari
La codifica dei campi di HTTP/3 consente di esprimere nomi di campo non validi nella sintassi usata da HTTP (vedere la Sezione 5.1 di [HTTP]). Le richieste o le risposte che contengono nomi di campo non validi DEVONO essere considerate malformate.
Analogamente, HTTP/3 può trasportare valori di campo non validi. Sebbene la maggior parte dei valori codificabili non alteri l'analisi dei campi, il ritorno a capo (ASCII 0x0d), la nuova riga (ASCII 0x0a) e il carattere nullo (ASCII 0x00), se convertiti letteralmente, possono essere sfruttati da un attaccante.
10.4. Memorizzabilità nella cache delle risposte push
Le risposte push non hanno una richiesta esplicita dal client; la richiesta è fornita dal server nel frame PUSH_PROMISE.
Quando più tenant condividono lo spazio sullo stesso server, il server DEVE assicurare che un tenant non possa inviare tramite push una rappresentazione di una risorsa per la quale non dispone dell'autorizzazione.
10.5. Considerazioni sulla negazione del servizio
Una connessione HTTP/3 può richiedere per il suo funzionamento un maggiore impegno di risorse rispetto a una connessione HTTP/1.1 o HTTP/2.
La possibilità di inviare elementi di protocollo non definiti che il pari deve ignorare può essere abusata, inducendo il pari a impiegare ulteriore tempo di elaborazione.
Gli endpoint che non monitorano tale comportamento si espongono al rischio di attacchi di negazione del servizio. Le implementazioni DOVREBBERO tenere traccia dell'uso di queste funzionalità e fissarne limiti d'uso.
10.5.1. Limiti sulla dimensione della sezione dei campi
Sezioni di campi di grandi dimensioni (Sezione 4.1) possono costringere un'implementazione a impegnare una grande quantità di stato. Un endpoint può usare l'impostazione SETTINGS_MAX_FIELD_SECTION_SIZE (Sezione 4.2.2) per comunicare al pari un limite che potrebbe essere applicato alla dimensione della sezione dei campi.
10.5.2. Problemi relativi a CONNECT
Il metodo CONNECT può essere usato per creare un carico sproporzionato su un proxy, poiché la creazione di stream è relativamente economica rispetto alla creazione e al mantenimento di connessioni TCP.
10.6. Uso della compressione
Quando comprime dati riservati nello stesso contesto di dati controllati da un attaccante, la compressione può permettere all'attaccante di recuperare i dati riservati. HTTP/3 abilita la compressione dei campi (Sezione 4.2).
Le implementazioni che comunicano su canali sicuri NON DEVONO comprimere contenuto che includa dati riservati e dati controllati dall'attaccante, a meno che non sia usato un contesto di compressione separato per ogni origine dei dati.
10.7. Padding e analisi del traffico
Il padding può essere usato per offuscare l'esatta dimensione del contenuto dei frame e per mitigare specifici attacchi a HTTP.
10.8. Analisi dei frame
Diversi elementi del protocollo contengono elementi di lunghezza annidati. Le implementazioni DEVONO assicurare che la lunghezza di un frame corrisponda esattamente alla lunghezza dei campi che contiene.
10.9. Dati anticipati
L'uso di 0-RTT con HTTP/3 comporta il rischio di attacchi di replay. Le mitigazioni anti-replay in [HTTP-REPLAY] DEVONO essere applicate quando HTTP/3 viene usato con 0-RTT.
10.10. Migrazione
Alcune implementazioni HTTP usano l'indirizzo del client per la registrazione o il controllo degli accessi. Poiché l'indirizzo di un client QUIC può cambiare durante la connessione, tali implementazioni devono recuperare attivamente l'indirizzo corrente del client o accettare esplicitamente che l'indirizzo originale possa cambiare.
10.11. Considerazioni sulla riservatezza
Diverse caratteristiche di HTTP/3 offrono agli osservatori l'opportunità di correlare nel tempo le operazioni di singoli client o server. Tra queste figurano i valori delle impostazioni, i tempi di reazione agli stimoli e l'elaborazione di qualsiasi funzionalità controllata dalle impostazioni.
La preferenza di HTTP/3 per l'uso di una singola connessione QUIC permette di correlare le attività di un utente su un sito.
11. Considerazioni IANA (IANA Considerations)
Questo documento registra un nuovo ID di protocollo ALPN (sezione 11.1) e crea nuovi registri che gestiscono l'assegnazione dei codepoint in HTTP/3.
11.1. Registrazione della stringa di identificazione HTTP/3 (Registration of HTTP/3 Identification String)
Questo documento crea, per l'identificazione di HTTP/3, una nuova registrazione nel registro "TLS Application-Layer Protocol Negotiation (ALPN) Protocol ID" stabilito da [RFC7301].
La stringa "h3" identifica HTTP/3:
- Protocollo (Protocol): HTTP/3
- Sequenza di identificazione (Identification Sequence): 0x68 0x33 (
"h3") - Specifica (Specification): questo documento
11.2. Nuovi registri (New Registries)
I nuovi registri creati in questo documento operano secondo la politica di registrazione QUIC documentata nella sezione 22.1 di [QUIC-TRANSPORT]. Tutti questi registri includono l'insieme comune di campi elencato nella sezione 22.1.1 di [QUIC-TRANSPORT]. I registri sono raccolti sotto l'intestazione "Hypertext Transfer Protocol version 3 (HTTP/3)".
Le assegnazioni iniziali in questi registri sono tutte designate come permanenti, con IETF come change controller e il gruppo di lavoro HTTP ([email protected]) come contatto.
11.2.1. Tipi di frame (Frame Types)
Questo documento istituisce un registro per i codici dei tipi di frame HTTP/3. Il registro "HTTP/3 Frame Types" gestisce uno spazio a 62 bit.
Tabella 2: tipi di frame HTTP/3 iniziali
| Tipo di frame (Frame Type) | Valore (Value) | Specifica (Specification) |
|---|---|---|
| DATA | 0x00 | Sezione 7.2.1 |
| HEADERS | 0x01 | Sezione 7.2.2 |
| Reserved | 0x02 | Questo documento |
| CANCEL_PUSH | 0x03 | Sezione 7.2.3 |
| SETTINGS | 0x04 | Sezione 7.2.4 |
| PUSH_PROMISE | 0x05 | Sezione 7.2.5 |
| Reserved | 0x06 | Questo documento |
| GOAWAY | 0x07 | Sezione 7.2.6 |
| MAX_PUSH_ID | 0x0d | Sezione 7.2.7 |
11.2.2. Parametri di impostazione (Settings Parameters)
Questo documento istituisce un registro per le impostazioni HTTP/3. Il registro "HTTP/3 Settings" gestisce uno spazio a 62 bit.
Tabella 3: impostazioni HTTP/3 iniziali
| Nome impostazione (Setting Name) | Valore (Value) | Specifica (Specification) | Predefinito (Default) |
|---|---|---|---|
| MAX_FIELD_SECTION_SIZE | 0x06 | Sezione 4.2.2 | Illimitato (Unlimited) |
11.2.3. Codici di errore (Error Codes)
Questo documento istituisce un registro per i codici di errore HTTP/3. Il registro "HTTP/3 Error Codes" gestisce uno spazio a 62 bit.
Le voci registrate da questo documento sono mostrate nella sezione 8.1.
11.2.4. Tipi di stream (Stream Types)
Questo documento istituisce un registro per i tipi di stream unidirezionali HTTP/3. Il registro "HTTP/3 Stream Types" gestisce uno spazio a 62 bit.
Tabella 5: tipi di stream HTTP/3 iniziali
| Tipo di stream (Stream Type) | Valore (Value) | Specifica (Specification) | Mittente (Sender) |
|---|---|---|---|
| Stream di controllo (Control Stream) | 0x00 | Sezione 6.2.1 | Entrambi (Both) |
| Stream push (Push Stream) | 0x01 | Sezione 4.6 | Server (Server) |
Appendice A. Considerazioni per la transizione da HTTP/2 (Considerations for Transitioning from HTTP/2)
HTTP/3 si basa sul design di HTTP/2 e condivide la semantica di base. Questa appendice riassume le principali differenze tra HTTP/2 e HTTP/3 per aiutare gli implementatori a comprendere la relazione tra i due protocolli.
A.1. Flussi (Streams)
HTTP/3 utilizza i flussi QUIC, mentre HTTP/2 utilizza un'astrazione di flusso su TCP. Differenze chiave:
- Identificatori di flusso: Gli ID di flusso in HTTP/3 sono assegnati da QUIC, non da HTTP/3
- Priorità dei flussi: HTTP/3 non include lo schema di priorità dei flussi di HTTP/2
- Controllo del flusso: HTTP/3 utilizza i meccanismi di controllo del flusso di QUIC
A.2. Tipi di frame HTTP (HTTP Frame Types)
Molti tipi di frame HTTP/2 sono preservati o modificati in HTTP/3:
Tipi di frame preservati:
- DATA (0x00) - Funzionalità simile
- HEADERS (0x01) - Funzionalità simile
- SETTINGS (0x04) - Simile ma solo sul flusso di controllo
- PUSH_PROMISE (0x05) - Funzionalità simile
- GOAWAY (0x07) - Funzionalità simile
Tipi di frame HTTP/2 rimossi o sostituiti:
- PRIORITY (0x02) - Rimosso in HTTP/3
- RST_STREAM (0x03) - Sostituito da RESET_STREAM di QUIC
- PING (0x06) - Sostituito dal frame PING di QUIC
- WINDOW_UPDATE (0x08) - Sostituito dal controllo del flusso di QUIC
- CONTINUATION (0x09) - Non necessario in HTTP/3
Nuovi tipi di frame in HTTP/3:
- CANCEL_PUSH (0x03) - Annullare il push del server
- MAX_PUSH_ID (0x0d) - Controllare lo spazio ID push
A.3. Parametri SETTINGS HTTP/2 (HTTP/2 SETTINGS Parameters)
Le impostazioni in HTTP/3 differiscono da HTTP/2:
Impostazioni rimosse:
- SETTINGS_HEADER_TABLE_SIZE - Sostituito dalle impostazioni QPACK
- SETTINGS_ENABLE_PUSH - Controllato tramite MAX_PUSH_ID
- SETTINGS_MAX_CONCURRENT_STREAMS - Controllato dai parametri di trasporto QUIC
- SETTINGS_INITIAL_WINDOW_SIZE - Sostituito dal controllo del flusso QUIC
- SETTINGS_MAX_FRAME_SIZE - Non necessario in HTTP/3
- SETTINGS_MAX_HEADER_LIST_SIZE - Sostituito da SETTINGS_MAX_FIELD_SECTION_SIZE
Impostazioni preservate:
- SETTINGS_MAX_FIELD_SECTION_SIZE (0x06) - Simile a SETTINGS_MAX_HEADER_LIST_SIZE di HTTP/2
A.4. Codici di errore HTTP/2 (HTTP/2 Error Codes)
HTTP/3 definisce il proprio insieme di codici di errore che differiscono dai codici di errore di HTTP/2. Gli implementatori dovrebbero notare le relazioni di mappatura ma non dovrebbero assumere una corrispondenza diretta uno-a-uno.
A.5. Altre differenze (Other Differences)
Gestione della connessione:
- HTTP/3 utilizza la gestione delle connessioni di QUIC, inclusa la migrazione della connessione e il supporto multipath
- Il preambolo di connessione di HTTP/2 non è necessario
Push del server:
- Il meccanismo di push del server in HTTP/3 è simile a HTTP/2 ma utilizza frame e tipi di flusso diversi
- Gli ID push sono espliciti in HTTP/3
Compressione dei campi:
- HTTP/3 utilizza QPACK invece di HPACK
- QPACK è progettato per gestire la consegna fuori ordine
Estensibilità:
- HTTP/3 fornisce meccanismi di estensione più flessibili
- I nuovi tipi di frame, impostazioni e tipi di flusso possono essere utilizzati senza negoziazione