4. Ausdruck der HTTP-Semantik in HTTP/3 (Expressing HTTP Semantics in HTTP/3)
4.1. HTTP-Nachrichtenrahmung (HTTP Message Framing)
Ein Client sendet eine HTTP-Anfrage auf einem Anforderungsstrom (Request Stream), bei dem es sich um einen vom Client initiierten bidirektionalen QUIC-Stream handelt; siehe Abschnitt 6.1. Ein Client MUSS (MUST) nur eine einzige Anfrage auf einem gegebenen Stream senden. Ein Server sendet null oder mehr vorläufige HTTP-Antworten (Interim HTTP Responses) auf demselben Stream wie die Anfrage, gefolgt von einer einzigen endgültigen HTTP-Antwort (Final HTTP Response), wie unten beschrieben. Siehe Abschnitt 15 von [HTTP] für eine Beschreibung vorläufiger und endgültiger HTTP-Antworten.
Push-Antworten (Pushed Responses) werden auf einem vom Server initiierten unidirektionalen QUIC-Stream gesendet; siehe Abschnitt 6.2.2. Ein Server sendet null oder mehr vorläufige HTTP-Antworten, gefolgt von einer einzigen endgültigen HTTP-Antwort, auf die gleiche Weise wie eine Standardantwort. Push wird in Abschnitt 4.6 ausführlicher beschrieben.
Auf einem gegebenen Stream MUSS (MUST) der Empfang mehrerer Anfragen oder der Empfang einer zusätzlichen HTTP-Antwort nach einer endgültigen HTTP-Antwort als fehlerhaft (Malformed) behandelt werden.
Eine HTTP-Nachricht (Anfrage oder Antwort) besteht aus:
-
dem Header-Abschnitt (Header Section), einschließlich Nachrichtensteuerungsdaten, gesendet als einzelner HEADERS-Frame,
-
optional dem Inhalt (Content), falls vorhanden, gesendet als eine Reihe von DATA-Frames, und
-
optional dem Trailer-Abschnitt (Trailer Section), falls vorhanden, gesendet als einzelner HEADERS-Frame.
Header- und Trailer-Abschnitte werden in den Abschnitten 6.3 und 6.5 von [HTTP] beschrieben; der Inhalt wird in Abschnitt 6.4 von [HTTP] beschrieben.
Der Empfang einer ungültigen Frame-Sequenz MUSS (MUST) als Verbindungsfehler (Connection Error) vom Typ H3_FRAME_UNEXPECTED behandelt werden. Insbesondere ein DATA-Frame vor einem HEADERS-Frame oder ein HEADERS- oder DATA-Frame nach dem abschließenden HEADERS-Frame wird als ungültig angesehen. Andere Frame-Typen, insbesondere unbekannte Frame-Typen, können gemäß ihren eigenen Regeln erlaubt sein; siehe Abschnitt 9.
Ein Server KANN (MAY) einen oder mehrere PUSH_PROMISE-Frames vor, nach oder verschachtelt mit den Frames einer Antwortnachricht senden. Diese PUSH_PROMISE-Frames sind nicht Teil der Antwort; siehe Abschnitt 4.6 für weitere Details. PUSH_PROMISE-Frames sind auf Push-Streams nicht erlaubt; eine Push-Antwort, die PUSH_PROMISE-Frames enthält, MUSS (MUST) als Verbindungsfehler vom Typ H3_FRAME_UNEXPECTED behandelt werden.
Frames unbekannter Typen (Abschnitt 9), einschließlich reservierter Frames (Reserved Frames) (Abschnitt 7.2.8), KÖNNEN (MAY) auf einem Anforderungs- oder Push-Stream vor, nach oder verschachtelt mit anderen in diesem Abschnitt beschriebenen Frames gesendet werden.
Die HEADERS- und PUSH_PROMISE-Frames können Aktualisierungen der dynamischen QPACK-Tabelle (Dynamic Table) referenzieren. Obwohl diese Aktualisierungen nicht direkt Teil des Nachrichtenaustauschs sind, müssen sie empfangen und verarbeitet werden, bevor die Nachricht verarbeitet werden kann. Siehe Abschnitt 4.2 für weitere Details.
Transfercodierungen (Transfer Codings) (siehe Abschnitt 7 von [HTTP/1.1]) sind für HTTP/3 nicht definiert; das Transfer-Encoding-Header-Feld DARF NICHT (MUST NOT) verwendet werden.
Eine Antwort KANN (MAY) aus mehreren Nachrichten bestehen, wenn und nur wenn eine oder mehrere vorläufige Antworten (1xx; siehe Abschnitt 15.2 von [HTTP]) einer endgültigen Antwort auf dieselbe Anfrage vorausgehen. Vorläufige Antworten enthalten keinen Inhalt oder Trailer-Abschnitte.
Ein HTTP-Anfrage/Antwort-Austausch verbraucht vollständig einen vom Client initiierten bidirektionalen QUIC-Stream. Nach dem Senden einer Anfrage MUSS (MUST) ein Client den Stream für das Senden schließen. Sofern nicht die CONNECT-Methode verwendet wird (siehe Abschnitt 4.4), DÜRFEN (MUST NOT) Clients das Schließen des Streams nicht vom Empfang einer Antwort auf ihre Anfrage abhängig machen. Nach dem Senden einer endgültigen Antwort MUSS (MUST) der Server den Stream für das Senden schließen. Zu diesem Zeitpunkt ist der QUIC-Stream vollständig geschlossen.
Wenn ein Stream geschlossen wird, zeigt dies das Ende der endgültigen HTTP-Nachricht an. Da einige Nachrichten groß oder unbegrenzt sind, SOLLTEN (SHOULD) Endpunkte mit der Verarbeitung teilweiser HTTP-Nachrichten beginnen, sobald genug von der Nachricht empfangen wurde, um Fortschritte zu erzielen. Wenn ein vom Client initiierter Stream endet, ohne genug von der HTTP-Nachricht zu haben, um eine vollständige Antwort bereitzustellen, SOLLTE (SHOULD) der Server seinen Antwort-Stream mit dem Fehlercode H3_REQUEST_INCOMPLETE abbrechen.
Ein Server kann eine vollständige Antwort senden, bevor der Client eine vollständige Anfrage sendet, wenn die Antwort nicht von einem Teil der Anfrage abhängt, der nicht gesendet und empfangen wurde. Wenn der Server den Rest der Anfrage nicht empfangen muss, KANN (MAY) er das Lesen des Anforderungsstroms abbrechen, eine vollständige Antwort senden und den sendenden Teil des Streams sauber schließen. Der Fehlercode H3_NO_ERROR SOLLTE (SHOULD) verwendet werden, wenn der Client aufgefordert wird, das Senden auf dem Anforderungsstrom zu beenden. Clients DÜRFEN (MUST NOT) vollständige Antworten nicht verwerfen, weil ihre Anfrage abrupt beendet wurde, obwohl Clients Antworten aus anderen Gründen jederzeit nach eigenem Ermessen verwerfen können. Wenn der Server eine teilweise oder vollständige Antwort sendet, aber das Lesen der Anfrage nicht abbricht, SOLLTEN (SHOULD) Clients den Inhalt der Anfrage weiter senden und den Stream normal schließen.
4.1.1. Anforderungsabbruch und -ablehnung (Request Cancellation and Rejection)
Sobald ein Anforderungsstrom geöffnet wurde, KANN (MAY) die Anfrage von einem der beiden Endpunkte abgebrochen werden. Clients brechen Anfragen ab, wenn die Antwort nicht mehr von Interesse ist; Server brechen Anfragen ab, wenn sie nicht in der Lage sind oder sich entscheiden, nicht zu antworten. Wenn möglich, wird EMPFOHLEN (RECOMMENDED), dass Server eine HTTP-Antwort mit einem geeigneten Statuscode senden, anstatt eine Anfrage abzubrechen, deren Verarbeitung bereits begonnen hat.
Implementierungen SOLLTEN (SHOULD) Anfragen abbrechen, indem sie alle Richtungen eines Streams, die noch offen sind, abrupt beenden. Dazu setzt eine Implementierung die sendenden Teile von Streams zurück und bricht das Lesen der empfangenden Teile von Streams ab; siehe Abschnitt 2.4 von [QUIC-TRANSPORT].
Wenn der Server eine Anfrage abbricht, ohne eine Anwendungsverarbeitung durchzuführen, wird die Anfrage als "abgelehnt" (Rejected) betrachtet. Der Server SOLLTE (SHOULD) seinen Antwort-Stream mit dem Fehlercode H3_REQUEST_REJECTED abbrechen. In diesem Kontext bedeutet "verarbeitet" (Processed), dass einige Daten aus dem Stream an eine höhere Softwareschicht übergeben wurden, die möglicherweise infolgedessen Maßnahmen ergriffen hat. Der Client kann vom Server abgelehnte Anfragen so behandeln, als wären sie niemals gesendet worden, wodurch sie später wiederholt werden können.
Server DÜRFEN (MUST NOT) den Fehlercode H3_REQUEST_REJECTED nicht für Anfragen verwenden, die teilweise oder vollständig verarbeitet wurden. Wenn ein Server eine Antwort nach teilweiser Verarbeitung aufgibt, SOLLTE (SHOULD) er seinen Antwort-Stream mit dem Fehlercode H3_REQUEST_CANCELLED abbrechen.
Client SOLLTE (SHOULD) den Fehlercode H3_REQUEST_CANCELLED verwenden, um Anfragen abzubrechen. Beim Empfang dieses Fehlercodes KANN (MAY) ein Server die Antwort abrupt mit dem Fehlercode H3_REQUEST_REJECTED beenden, wenn keine Verarbeitung durchgeführt wurde. Clients DÜRFEN (MUST NOT) den Fehlercode H3_REQUEST_REJECTED nicht verwenden, es sei denn, ein Server hat das Schließen des Anforderungsstroms mit diesem Fehlercode angefordert.
Wenn ein Stream nach dem Empfang einer vollständigen Antwort abgebrochen wird, KANN (MAY) der Client den Abbruch ignorieren und die Antwort verwenden. Wenn jedoch ein Stream nach dem Empfang einer teilweisen Antwort abgebrochen wird, SOLLTE (SHOULD NOT) die Antwort nicht verwendet werden. Nur idempotente Aktionen (Idempotent Actions) wie GET, PUT oder DELETE können sicher wiederholt werden; ein Client SOLLTE (SHOULD NOT) eine Anfrage mit einer nicht-idempotenten Methode nicht automatisch wiederholen, es sei denn, er hat eine Möglichkeit zu wissen, dass die Anforderungssemantik unabhängig von der Methode idempotent ist, oder eine Möglichkeit zu erkennen, dass die ursprüngliche Anfrage niemals angewendet wurde. Siehe Abschnitt 9.2.2 von [HTTP] für weitere Details.
4.1.2. Fehlerhafte Anfragen und Antworten (Malformed Requests and Responses)
Eine fehlerhafte Anfrage oder Antwort ist eine ansonsten gültige Frame-Sequenz, die jedoch aus folgenden Gründen ungültig ist:
-
das Vorhandensein verbotener Felder oder Pseudo-Header-Felder (Pseudo-Header Fields),
-
das Fehlen obligatorischer Pseudo-Header-Felder,
-
ungültige Werte für Pseudo-Header-Felder,
-
Pseudo-Header-Felder nach Feldern,
-
eine ungültige Sequenz von HTTP-Nachrichten,
-
die Aufnahme von Feldnamen in Großbuchstaben oder
-
die Aufnahme ungültiger Zeichen in Feldnamen oder -werten.
Eine Anfrage oder Antwort, die als Inhalt habend definiert ist, wenn sie ein Content-Length-Header-Feld (Abschnitt 8.6 von [HTTP]) enthält, ist fehlerhaft, wenn der Wert des Content-Length-Header-Feldes nicht der Summe der empfangenen DATA-Frame-Längen entspricht. Eine Antwort, die als niemals Inhalt habend definiert ist, selbst wenn ein Content-Length vorhanden ist, kann ein Content-Length-Header-Feld ungleich Null haben, obwohl kein Inhalt in DATA-Frames enthalten ist.
Vermittler, die HTTP-Anfragen oder -Antworten verarbeiten (d. h. jeder Vermittler, der nicht als Tunnel fungiert), DÜRFEN (MUST NOT) eine fehlerhafte Anfrage oder Antwort nicht weiterleiten. Fehlerhafte Anfragen oder Antworten, die erkannt werden, MÜSSEN (MUST) als Stream-Fehler (Stream Error) vom Typ H3_MESSAGE_ERROR behandelt werden.
Für fehlerhafte Anfragen KANN (MAY) ein Server eine HTTP-Antwort senden, die den Fehler anzeigt, bevor der Stream geschlossen oder zurückgesetzt wird. Clients DÜRFEN (MUST NOT) eine fehlerhafte Antwort nicht akzeptieren. Beachten Sie, dass diese Anforderungen dazu dienen, vor mehreren Arten gängiger Angriffe auf HTTP zu schützen; sie sind absichtlich streng, da Nachsicht Implementierungen diesen Schwachstellen aussetzen kann.
4.2. HTTP-Felder (HTTP Fields)
HTTP-Nachrichten tragen Metadaten als eine Reihe von Schlüssel-Wert-Paaren, die "HTTP-Felder" (HTTP Fields) genannt werden; siehe Abschnitte 6.3 und 6.5 von [HTTP]. Für eine Auflistung registrierter HTTP-Felder siehe das "Hypertext Transfer Protocol (HTTP) Field Name Registry", das unter https://www.iana.org/assignments/http-fields/ geführt wird. Wie HTTP/2 hat HTTP/3 zusätzliche Überlegungen in Bezug auf die Verwendung von Zeichen in Feldnamen, das Connection-Header-Feld und Pseudo-Header-Felder.
Feldnamen sind Zeichenfolgen, die eine Teilmenge von ASCII-Zeichen enthalten. Eigenschaften von HTTP-Feldnamen und -werten werden ausführlicher in Abschnitt 5.1 von [HTTP] erörtert. Zeichen in Feldnamen MÜSSEN (MUST) vor ihrer Codierung in Kleinbuchstaben umgewandelt werden. Eine Anfrage oder Antwort, die Großbuchstaben in Feldnamen enthält, MUSS (MUST) als fehlerhaft behandelt werden.
HTTP/3 verwendet das Connection-Header-Feld nicht, um verbindungsspezifische Felder anzuzeigen; in diesem Protokoll werden verbindungsspezifische Metadaten auf andere Weise übermittelt. Ein Endpunkt DARF (MUST NOT) keinen HTTP/3-Feldabschnitt erzeugen, der verbindungsspezifische Felder enthält; jede Nachricht, die verbindungsspezifische Felder enthält, MUSS (MUST) als fehlerhaft behandelt werden.
Die einzige Ausnahme hiervon ist das TE-Header-Feld, das in einem HTTP/3-Anforderungsheader vorhanden sein KANN (MAY); wenn es vorhanden ist, DARF (MUST NOT) es keinen anderen Wert als "trailers" enthalten.
Ein Vermittler, der eine HTTP/1.x-Nachricht in HTTP/3 umwandelt, MUSS (MUST) verbindungsspezifische Header-Felder entfernen, wie in Abschnitt 7.6.1 von [HTTP] besprochen, sonst werden ihre Nachrichten von anderen HTTP/3-Endpunkten als fehlerhaft behandelt.
4.2.1. Feldkomprimierung (Field Compression)
[QPACK] beschreibt eine Variation von HPACK, die einem Encoder eine gewisse Kontrolle darüber gibt, wie viel Head-of-Line-Blocking (Head-of-Line Blocking) durch Komprimierung verursacht werden kann. Dies ermöglicht es einem Encoder, Komprimierungseffizienz mit Latenz auszugleichen. HTTP/3 verwendet QPACK, um Header- und Trailer-Abschnitte zu komprimieren, einschließlich der im Header-Abschnitt vorhandenen Steuerungsdaten.
Um eine bessere Komprimierungseffizienz zu ermöglichen, KANN (MAY) das Cookie-Header-Feld ([COOKIES]) vor der Komprimierung in separate Feldzeilen aufgeteilt werden, jede mit einem oder mehreren Cookie-Paaren (Cookie-Pairs). Wenn ein dekomprimierter Feldabschnitt mehrere Cookie-Feldzeilen enthält, MÜSSEN (MUST) diese vor der Übergabe an einen anderen Kontext als HTTP/2 oder HTTP/3, wie eine HTTP/1.1-Verbindung oder eine generische HTTP-Serveranwendung, mit dem Zwei-Byte-Trennzeichen "; " (ASCII 0x3b, 0x20) zu einer einzigen Bytezeichenfolge verkettet werden.
4.2.2. Header-Größenbeschränkungen (Header Size Constraints)
Eine HTTP/3-Implementierung KANN (MAY) eine Begrenzung der maximalen Größe des Nachrichten-Headers auferlegen, die sie für eine einzelne HTTP-Nachricht akzeptiert. Ein Server, der einen größeren Header-Abschnitt erhält, als er bereit ist zu verarbeiten, kann einen HTTP-431-Statuscode (Request Header Fields Too Large) ([RFC6585]) senden. Ein Client kann Antworten verwerfen, die er nicht verarbeiten kann. Die Größe einer Feldliste wird basierend auf der unkomprimierten Größe der Felder berechnet, einschließlich der Länge des Namens und Werts in Bytes plus einem Overhead von 32 Bytes für jedes Feld.
Wenn eine Implementierung ihren Peer über diese Grenze informieren möchte, kann sie als Anzahl von Bytes im Parameter SETTINGS_MAX_FIELD_SECTION_SIZE übermittelt werden. Eine Implementierung, die diesen Parameter erhalten hat, SOLLTE (SHOULD NOT) keinen HTTP-Nachrichten-Header senden, der die angegebene Größe überschreitet, da der Peer ihn wahrscheinlich ablehnen wird. Eine HTTP-Nachricht kann jedoch einen oder mehrere Vermittler durchlaufen, bevor sie den Ursprungsserver erreicht; siehe Abschnitt 3.7 von [HTTP]. Da diese Grenze von jeder Implementierung, die die Nachricht verarbeitet, separat angewendet wird, sind Nachrichten unterhalb dieser Grenze nicht garantiert akzeptiert zu werden.
4.3. HTTP-Steuerungsdaten (HTTP Control Data)
Wie HTTP/2 verwendet HTTP/3 eine Reihe von Pseudo-Header-Feldern (Pseudo-Header Fields), bei denen der Feldname mit dem Zeichen : (ASCII 0x3a) beginnt. Diese Pseudo-Header-Felder übermitteln Nachrichtensteuerungsdaten; siehe Abschnitt 6.2 von [HTTP].
Pseudo-Header-Felder sind keine HTTP-Felder. Endpunkte DÜRFEN (MUST NOT) keine anderen Pseudo-Header-Felder als die in diesem Dokument definierten erzeugen. Eine Erweiterung könnte jedoch eine Änderung dieser Einschränkung aushandeln; siehe Abschnitt 9.
Pseudo-Header-Felder sind nur in dem Kontext gültig, in dem sie definiert sind. Für Anfragen definierte Pseudo-Header-Felder DÜRFEN (MUST NOT) nicht in Antworten erscheinen; für Antworten definierte Pseudo-Header-Felder DÜRFEN (MUST NOT) nicht in Anfragen erscheinen. Pseudo-Header-Felder DÜRFEN (MUST NOT) nicht in Trailer-Abschnitten erscheinen. Endpunkte MÜSSEN (MUST) eine Anfrage oder Antwort, die undefinierte oder ungültige Pseudo-Header-Felder enthält, als fehlerhaft behandeln.
Alle Pseudo-Header-Felder MÜSSEN (MUST) im Header-Abschnitt vor regulären Header-Feldern erscheinen. Jede Anfrage oder Antwort, die ein Pseudo-Header-Feld enthält, das in einem Header-Abschnitt nach einem regulären Header-Feld erscheint, MUSS (MUST) als fehlerhaft behandelt werden.
4.3.1. Anforderungs-Pseudo-Header-Felder (Request Pseudo-Header Fields)
Die folgenden Pseudo-Header-Felder sind für Anfragen definiert:
":method": Enthält die HTTP-Methode (HTTP Method) (Abschnitt 9 von [HTTP])
":scheme": Enthält den Scheme-Teil der Ziel-URI (Abschnitt 3.1 von [URI]).
Der :scheme-Pseudo-Header ist nicht auf URIs mit den Schemes "http" und "https" beschränkt. Ein Proxy oder Gateway kann Anfragen für Nicht-HTTP-Schemes übersetzen und so die Verwendung von HTTP für die Interaktion mit Nicht-HTTP-Diensten ermöglichen.
Siehe Abschnitt 3.1.2 für Anleitungen zur Verwendung eines anderen Schemes als "https".
":authority": Enthält den Authority-Teil der Ziel-URI (Abschnitt 3.2 von [URI]). Die Authority DARF (MUST NOT) die veraltete Userinfo-Unterkomponente für URIs des Schemes "http" oder "https" nicht enthalten.
Um sicherzustellen, dass die HTTP/1.1-Anforderungszeile genau reproduziert werden kann, MUSS (MUST) dieses Pseudo-Header-Feld bei der Übersetzung aus einer HTTP/1.1-Anforderung, die ein Anforderungsziel in einer methodenspezifischen Form hat, weggelassen werden; siehe Abschnitt 7.1 von [HTTP]. Clients, die HTTP/3-Anforderungen direkt generieren, SOLLTEN (SHOULD) das :authority-Pseudo-Header-Feld anstelle des Host-Header-Feldes verwenden. Ein Vermittler, der eine HTTP/3-Anforderung in HTTP/1.1 konvertiert, MUSS (MUST) ein Host-Feld erstellen, wenn eines nicht in einer Anfrage vorhanden ist, indem der Wert des :authority-Pseudo-Header-Feldes kopiert wird.
":path": Enthält die Pfad- und Query-Teile der Ziel-URI (die "path-absolute"-Produktion und optional ein ?-Zeichen (ASCII 0x3f), gefolgt von der "query"-Produktion; siehe Abschnitte 3.3 und 3.4 von [URI]).
Dieses Pseudo-Header-Feld DARF (MUST NOT) für "http"- oder "https"-URIs nicht leer sein; "http"- oder "https"-URIs, die keine Pfadkomponente enthalten, MÜSSEN (MUST) einen Wert von / (ASCII 0x2f) enthalten. Eine OPTIONS-Anforderung, die keine Pfadkomponente enthält, enthält den Wert * (ASCII 0x2a) für das :path-Pseudo-Header-Feld; siehe Abschnitt 7.1 von [HTTP].
Alle HTTP/3-Anforderungen MÜSSEN (MUST) genau einen Wert für die :method-, :scheme- und :path-Pseudo-Header-Felder enthalten, es sei denn, die Anforderung ist eine CONNECT-Anforderung; siehe Abschnitt 4.4.
Wenn das :scheme-Pseudo-Header-Feld ein Schema identifiziert, das eine obligatorische Authority-Komponente hat (einschließlich "http" und "https"), MUSS (MUST) die Anforderung entweder ein :authority-Pseudo-Header-Feld oder ein Host-Header-Feld enthalten. Wenn diese Felder vorhanden sind, DÜRFEN (MUST NOT) sie nicht leer sein. Wenn beide Felder vorhanden sind, MÜSSEN (MUST) sie denselben Wert enthalten. Wenn das Schema keine obligatorische Authority-Komponente hat und keine im Anforderungsziel bereitgestellt wird, DARF (MUST NOT) die Anforderung das :authority-Pseudo-Header- oder Host-Header-Feld nicht enthalten.
Eine HTTP-Anforderung, die obligatorische Pseudo-Header-Felder weglässt oder ungültige Werte für diese Pseudo-Header-Felder enthält, ist fehlerhaft.
HTTP/3 definiert keine Möglichkeit, die Versionskennung zu übertragen, die in der HTTP/1.1-Anforderungszeile enthalten ist. HTTP/3-Anforderungen haben implizit eine Protokollversion von "3.0".
4.3.2. Antwort-Pseudo-Header-Felder (Response Pseudo-Header Fields)
Für Antworten ist ein einzelnes ":status"-Pseudo-Header-Feld definiert, das den HTTP-Statuscode trägt; siehe Abschnitt 15 von [HTTP]. Dieses Pseudo-Header-Feld MUSS (MUST) in allen Antworten enthalten sein; andernfalls ist die Antwort fehlerhaft (siehe Abschnitt 4.1.2).
HTTP/3 definiert keine Möglichkeit, die Version oder den Grund-Satz (Reason Phrase) zu übertragen, der in einer HTTP/1.1-Statuszeile enthalten ist. HTTP/3-Antworten haben implizit eine Protokollversion von "3.0".
4.4. Die CONNECT-Methode (The CONNECT Method)
Die CONNECT-Methode fordert den Empfänger auf, einen Tunnel (Tunnel) zum durch das Anforderungsziel identifizierten Ziel-Ursprungsserver herzustellen; siehe Abschnitt 9.3.6 von [HTTP]. Sie wird hauptsächlich mit HTTP-Proxys verwendet, um eine TLS-Sitzung mit einem Ursprungsserver herzustellen, um mit "https"-Ressourcen zu interagieren.
In HTTP/1.x wird CONNECT verwendet, um eine gesamte HTTP-Verbindung in einen Tunnel zu einem entfernten Host umzuwandeln. In HTTP/2 und HTTP/3 wird die CONNECT-Methode verwendet, um einen Tunnel über einen einzelnen Stream herzustellen.
Eine CONNECT-Anforderung MUSS (MUST) wie folgt aufgebaut sein:
-
Das :method-Pseudo-Header-Feld wird auf "CONNECT" gesetzt
-
Die :scheme- und :path-Pseudo-Header-Felder werden weggelassen
-
Das :authority-Pseudo-Header-Feld enthält den Host und Port, zu dem eine Verbindung hergestellt werden soll (entspricht der Authority-Form des Anforderungsziels von CONNECT-Anforderungen; siehe Abschnitt 7.1 von [HTTP]).
Der Anforderungsstrom bleibt am Ende der Anforderung offen, um die zu übertragenden Daten zu transportieren. Eine CONNECT-Anforderung, die diesen Einschränkungen nicht entspricht, ist fehlerhaft.
Ein Proxy, der CONNECT unterstützt, stellt eine TCP-Verbindung ([RFC0793]) zum im :authority-Pseudo-Header-Feld identifizierten Server her. Sobald diese Verbindung erfolgreich hergestellt ist, sendet der Proxy einen HEADERS-Frame mit einem Statuscode der 2xx-Serie an den Client, wie in Abschnitt 15.3 von [HTTP] definiert.
Alle DATA-Frames auf dem Stream entsprechen Daten, die auf der TCP-Verbindung gesendet oder empfangen wurden. Die Nutzlast jedes vom Client gesendeten DATA-Frames wird vom Proxy an den TCP-Server übertragen; vom TCP-Server empfangene Daten werden vom Proxy in DATA-Frames verpackt. Beachten Sie, dass die Größe und Anzahl der TCP-Segmente nicht garantiert vorhersehbar auf die Größe und Anzahl der HTTP-DATA- oder QUIC-STREAM-Frames abgebildet werden.
Sobald die CONNECT-Methode abgeschlossen ist, dürfen nur DATA-Frames auf dem Stream gesendet werden. Erweiterungs-Frames KÖNNEN (MAY) verwendet werden, wenn dies durch die Definition der Erweiterung ausdrücklich erlaubt ist. Der Empfang eines anderen bekannten Frame-Typs MUSS (MUST) als Verbindungsfehler vom Typ H3_FRAME_UNEXPECTED behandelt werden.
Die TCP-Verbindung kann von jedem Peer geschlossen werden. Wenn der Client den Anforderungsstrom beendet (d. h. der Empfangsstrom am Proxy wechselt in den Zustand "Data Recvd"), setzt der Proxy das FIN-Bit auf seiner Verbindung zum TCP-Server. Wenn der Proxy ein Paket mit gesetztem FIN-Bit empfängt, schließt er den Sendestrom, den er an den Client sendet. TCP-Verbindungen, die in einer einzelnen Richtung halb geschlossen (Half-Closed) bleiben, sind nicht ungültig, werden jedoch oft von Servern schlecht behandelt, sodass Clients SOLLTEN (SHOULD NOT) einen Stream zum Senden nicht schließen, während sie noch erwarten, Daten vom Ziel des CONNECT zu empfangen.
Ein TCP-Verbindungsfehler wird durch abruptes Beenden des Streams signalisiert. Ein Proxy behandelt jeden Fehler in der TCP-Verbindung, einschließlich des Empfangs eines TCP-Segments mit gesetztem RST-Bit, als Stream-Fehler vom Typ H3_CONNECT_ERROR.
Entsprechend, wenn ein Proxy einen Fehler mit dem Stream oder der QUIC-Verbindung erkennt, MUSS (MUST) er die TCP-Verbindung schließen. Wenn der Proxy erkennt, dass der Client den Stream zurückgesetzt oder das Lesen vom Stream abgebrochen hat, MUSS (MUST) er die TCP-Verbindung schließen. Wenn der Stream zurückgesetzt wird oder das Lesen vom Client abgebrochen wird, SOLLTE (SHOULD) ein Proxy denselben Vorgang in der anderen Richtung ausführen, um sicherzustellen, dass beide Richtungen des Streams abgebrochen werden. In all diesen Fällen SOLLTE (SHOULD) der Proxy, wenn die zugrunde liegende TCP-Implementierung dies zulässt, ein TCP-Segment mit gesetztem RST-Bit senden.
Da CONNECT einen Tunnel zu einem beliebigen Server erstellt, SOLLTEN (SHOULD) Proxys, die CONNECT unterstützen, seine Verwendung auf eine Reihe bekannter Ports oder eine Liste sicherer Anforderungsziele beschränken; siehe Abschnitt 9.3.6 von [HTTP] für weitere Details.
4.5. HTTP-Upgrade (HTTP Upgrade)
HTTP/3 unterstützt weder den HTTP-Upgrade-Mechanismus (HTTP Upgrade Mechanism) (Abschnitt 7.8 von [HTTP]) noch den Informationsstatuscode 101 (Switching Protocols) (Abschnitt 15.2.2 von [HTTP]).
4.6. Server-Push (Server Push)
Server-Push (Server Push) ist ein Interaktionsmodus, der es einem Server ermöglicht, einen Anfrage-Antwort-Austausch an einen Client zu pushen, in Erwartung der Anfrage des Clients. Ein Client kann Server-Push deaktivieren, indem er SETTINGS_ENABLE_PUSH in einem SETTINGS-Frame auf 0 setzt. Ein Server DARF (MUST NOT) keinen Push an einen Client senden, der SETTINGS_ENABLE_PUSH auf 0 gesetzt hat; Serververhalten, das dies verletzt, MUSS (MUST) als Verbindungsfehler vom Typ H3_SETTINGS_ERROR behandelt werden.
Wie HTTP/2 initiiert der Server einen Push, indem er einen PUSH_PROMISE-Frame (Abschnitt 7.2.5) auf einem vom Client initiierten Anforderungsstrom sendet. Die Push-ID (Push ID) wird verwendet, um einen Server-Push zu identifizieren (siehe Abschnitt 4.6.1). Die Push-ID wird im PUSH_PROMISE-Frame übertragen, der auch einen Anforderungs-Header-Abschnitt enthält, der der vom Server generierten Anforderung zugeordnet ist, wie in Abschnitt 15 von [HTTP] beschrieben.
Der Server sendet die Antwort von einem von ihm initiierten Push-Stream (Abschnitt 6.2.2). Die Zustellung der gepushten Antwort ist identisch mit der einer Antwort auf eine reguläre Anforderung. Der Antwort-Header-Abschnitt für die gepushte Antwort wird in einem HEADERS-Frame übertragen, wie in Abschnitt 7.2.4 beschrieben. Ein Server kann einen versprochenen Push abbrechen, indem er einen CANCEL_PUSH-Frame mit der Push-ID auf dem Push-Stream sendet.
Clients steuern die Anzahl der Pushs, die der Server versprechen kann, mithilfe des MAX_PUSH_ID-Frames (Abschnitt 7.2.7). Ein Server DARF (MUST NOT) keinen PUSH_PROMISE-Frame oder CANCEL_PUSH-Frame mit einer Push-ID senden, die größer ist als die maximale Push-ID, die der Client für die Verbindung bereitgestellt hat. Clients MÜSSEN (MUST) einen Versuch, dies zu tun, als Verbindungsfehler vom Typ H3_ID_ERROR behandeln.
Sobald ein Push-Stream durch einen PUSH_PROMISE-Frame geöffnet oder reserviert wurde, kann der Push-Stream verwendet werden, solange der Client den Push nicht abgebrochen hat. Sobald ein Client einen CANCEL_PUSH-Frame vom Steuerungsstrom oder eine Stream-Beendigung vom Push-Stream empfängt, wird der Push abgebrochen. Wenn der Push-Stream ohne CANCEL_PUSH beendet wird, gilt der Push immer noch als erfolgreich abgeschlossen.
Clients können einen Push abbrechen, indem sie einen CANCEL_PUSH-Frame senden. Nachdem der Server ihn empfangen hat, MUSS (MUST) der Server das Senden des Pushs abbrechen, wenn der Push noch nicht abgeschlossen ist. Clients können einen Push auch abbrechen, indem sie den Push-Stream zurücksetzen. In beiden Fällen kann der Empfänger jeden empfangenen Push-Antwortstatus sicher verwerfen.
Sobald ein Anforderungsstrom geschlossen wird, können Implementierungen wählen, nur eine Referenz auf die Push-Antwort zu puffern oder die Referenz auf die Push-Antwort vollständig zu entfernen. Wenn eine Push-Antwort empfangen wird und der zugehörige Anforderungsstrom geschlossen ist, zeigt dies keinen Fehler des Pushs an.
Push-Streams werden immer durch eine Push-ID referenziert. Der Empfänger eines PUSH_PROMISE-Frames ordnet die Push-ID einem vom Client initiierten Stream zu, und ein Client, der einen HEADERS-Frame auf einem Push-Stream empfängt, gleicht die Push-ID mit einem empfangenen Push ab.
4.6.1. Push-IDs (Push IDs)
Push-IDs sind 62-Bit-Ganzzahlen ohne Vorzeichen (siehe Abschnitt 16 von [QUIC-TRANSPORT]), die zur Identifizierung eines Server-Pushs verwendet werden. Push-IDs sind für die Lebensdauer der Verbindung eindeutig.
Der Push-ID-Raum beginnt bei Null und ist eine Teilmenge des ganzzahligen Raums; daher können Push-IDs nicht in Kontexten erscheinen, die eine Stream-ID oder eine Anforderungs-ID erfordern. Insbesondere ist es Push-IDs nicht gestattet, in GOAWAY-Frames zu erscheinen (siehe Abschnitt 5.2).
Push-IDs werden in einem einzelnen PUSH_PROMISE-Frame (siehe Abschnitt 7.2.5) und einem einzelnen Push-Stream (siehe Abschnitte 4.6 und 6.2.2) verwendet. Diese Verwendungen MÜSSEN (MUST) auf denselben versprochenen Push verweisen, den der Server während der Lebensdauer der Verbindung gemacht hat.
Nach dem Senden einer Push-Antwort auf einem Push-Stream kann die Push-ID nicht wiederverwendet werden. Wenn ein Client einen anderen Push-Stream-Header oder ein anderes PUSH_PROMISE auf derselben Push-ID von verschiedenen Streams empfängt, MUSS (MUST) dies als Verbindungsfehler vom Typ H3_ID_ERROR behandelt werden.