Zum Hauptinhalt springen

RFC 9114 - HTTP/3

  • Status: Proposed Standard
  • Veröffentlicht: June 2022
  • Stream: IETF
  • Errata: Keine Errata

Zusammenfassung (Abstract)​

Das QUIC-Transportprotokoll (QUIC Transport Protocol) verfügt über mehrere Funktionen, die für einen HTTP-Transport wünschenswert sind, wie Stream-Multiplexing (Stream Multiplexing), Stream-bezogene Flusskontrolle (Per-Stream Flow Control) und Verbindungsaufbau mit niedriger Latenz (Low-Latency Connection Establishment). Dieses Dokument beschreibt eine Zuordnung der HTTP-Semantik über QUIC. Dieses Dokument identifiziert auch HTTP/2-Funktionen, die von QUIC subsumiert werden, und beschreibt, wie HTTP/2-Erweiterungen auf HTTP/3 portiert werden können.


Status dieses Memos (Status of This Memo)​

Dies ist ein Internet Standards Track-Dokument.

Dieses Dokument ist ein Produkt der Internet Engineering Task Force (IETF). Es repräsentiert den Konsens der IETF-Community. Es wurde öffentlich geprüft und zur Veröffentlichung durch die Internet Engineering Steering Group (IESG) genehmigt. Weitere Informationen zu Internet-Standards sind in Abschnitt 2 von RFC 7841 verfügbar.

Informationen über den aktuellen Status dieses Dokuments, Errata und wie Feedback gegeben werden kann, sind unter https://www.rfc-editor.org/info/rfc9114 erhältlich.


Inhaltsverzeichnis (Table of Contents)​

Hauptkapitel​

Anhänge​


Verwandte Ressourcen​



1. Introduction (Einführung)​

HTTP-Semantik (HTTP Semantics) ([HTTP]) wird für eine breite Palette von Diensten im Internet verwendet. Diese Semantik wurde am häufigsten mit HTTP/1.1 und HTTP/2 verwendet. HTTP/1.1 wurde über verschiedene Transport- und Sitzungsschichten verwendet, während HTTP/2 hauptsächlich mit TLS über TCP verwendet wurde. HTTP/3 unterstützt dieselbe Semantik über ein neues Transportprotokoll: QUIC.

1.1. Prior Versions of HTTP (Frühere Versionen von HTTP)​

HTTP/1.1 ([HTTP/1.1]) verwendet durch Leerzeichen getrennte Textfelder zur Übertragung von HTTP-Nachrichten. Während diese Austausche für Menschen lesbar sind, führt die Verwendung von Leerzeichen für die Nachrichtenformatierung zu Parsing-Komplexität und übermäßiger Toleranz gegenüber variantem Verhalten.

Da HTTP/1.1 keine Multiplexing-Schicht (Multiplexing Layer) enthält, werden häufig mehrere TCP-Verbindungen verwendet, um Anfragen parallel zu bearbeiten. Dies hat jedoch negative Auswirkungen auf die Staukontrolle (Congestion Control) und die Netzwerkeffizienz, da TCP die Staukontrolle nicht über mehrere Verbindungen hinweg teilt.

HTTP/2 ([HTTP/2]) führte eine binäre Framing- (Binary Framing) und Multiplexing-Schicht ein, um die Latenz zu verbessern, ohne die Transportschicht zu ändern. Da jedoch die parallele Natur des Multiplexing von HTTP/2 für die Verlustrückgewinnungsmechanismen (Loss Recovery Mechanisms) von TCP nicht sichtbar ist, führt ein verlorenes oder neu geordnetes Paket dazu, dass alle aktiven Transaktionen einen Stillstand (Stall) erleben, unabhängig davon, ob diese Transaktion direkt vom verlorenen Paket betroffen war.

1.2. Delegation to QUIC (Delegation an QUIC)​

Das QUIC-Transportprotokoll (QUIC Transport Protocol) integriert Stream-Multiplexing (Stream Multiplexing) und Stream-bezogene Flusskontrolle (Per-Stream Flow Control), ähnlich dem, was durch die HTTP/2-Framing-Schicht bereitgestellt wird. Durch die Bereitstellung von Zuverlässigkeit (Reliability) auf Stream-Ebene und Staukontrolle über die gesamte Verbindung hat QUIC die Fähigkeit, die Leistung von HTTP im Vergleich zu einer TCP-Zuordnung zu verbessern. QUIC integriert auch TLS 1.3 ([TLS]) auf der Transportschicht und bietet vergleichbare Vertraulichkeit (Confidentiality) und Integrität (Integrity) wie die Ausführung von TLS über TCP, mit der verbesserten Verbindungsaufbau-Latenz von TCP Fast Open ([TFO]).

Dieses Dokument definiert HTTP/3: eine Zuordnung der HTTP-Semantik über das QUIC-Transportprotokoll, die stark auf dem Design von HTTP/2 basiert. HTTP/3 verlässt sich auf QUIC, um Vertraulichkeit und Integritätsschutz von Daten, Peer-Authentifizierung (Peer Authentication) und zuverlässige, geordnete, stream-weise Zustellung bereitzustellen. Während Stream-Lebensdauer (Stream Lifetime) und Flusskontroll-Probleme an QUIC delegiert werden, wird auf jedem Stream ein binäres Framing ähnlich dem HTTP/2-Framing verwendet. Einige HTTP/2-Funktionen werden von QUIC subsumiert, während andere Funktionen auf QUIC aufgebaut werden.

QUIC wird in [QUIC-TRANSPORT] beschrieben. Eine vollständige Beschreibung von HTTP/2 finden Sie in [HTTP/2].



2. HTTP/3 Protocol Overview (HTTP/3-Protokollübersicht)​

HTTP/3 bietet einen Transport für HTTP-Semantik unter Verwendung des QUIC-Transportprotokolls (QUIC Transport Protocol) und einer internen Framing-Schicht (Framing Layer), die HTTP/2 ähnelt.

Sobald ein Client weiß, dass an einem bestimmten Endpunkt ein HTTP/3-Server existiert, öffnet er eine QUIC-Verbindung. QUIC bietet Protokollverhandlung (Protocol Negotiation), streambasiertes Multiplexing (Stream-Based Multiplexing) und Flusskontrolle (Flow Control). Die Erkennung eines HTTP/3-Endpunkts wird in Abschnitt 3.1 beschrieben.

Innerhalb jedes Streams ist die Grundeinheit der HTTP/3-Kommunikation ein Frame (Abschnitt 7.2). Jeder Frame-Typ dient einem anderen Zweck. Beispielsweise bilden HEADERS- und DATA-Frames die Grundlage von HTTP-Anfragen und -Antworten (Abschnitt 4.1). Frames, die für die gesamte Verbindung gelten, werden über einen dedizierten Kontrollstream (Control Stream) übertragen.

Das Multiplexing von Anfragen wird unter Verwendung der QUIC-Stream-Abstraktion (Stream Abstraction) durchgeführt, die in Abschnitt 2 von [QUIC-TRANSPORT] beschrieben wird. Jedes Anfrage-Antwort-Paar verbraucht einen einzelnen QUIC-Stream. Streams sind unabhängig voneinander, sodass ein blockierter Stream oder ein Stream mit Paketverlust den Fortschritt anderer Streams nicht verhindert.

Server-Push (Server Push) ist ein in HTTP/2 ([HTTP/2]) eingeführter Interaktionsmodus, der es einem Server ermöglicht, einen Anfrage-Antwort-Austausch an einen Client zu pushen, in Erwartung, dass der Client die angegebene Anfrage stellt. Dies tauscht Netzwerknutzung gegen einen potenziellen Latenzgewinn. Mehrere HTTP/3-Frames werden zur Verwaltung von Server-Push verwendet, wie PUSH_PROMISE, MAX_PUSH_ID und CANCEL_PUSH.

Wie in HTTP/2 werden Anfrage- und Antwortfelder (Fields) für die Übertragung komprimiert. Da HPACK ([HPACK]) auf der geordneten Übertragung komprimierter Feldabschnitte (Field Sections) beruht (eine Garantie, die QUIC nicht bietet), ersetzt HTTP/3 HPACK durch QPACK ([QPACK]). QPACK verwendet separate unidirektionale Streams, um den Feldtabellenstatus (Field Table State) zu ändern und zu verfolgen, während codierte Feldabschnitte auf den Status der Tabelle verweisen, ohne ihn zu ändern.

2.1. Document Organization (Dokumentorganisation)​

Die folgenden Abschnitte bieten einen detaillierten Überblick über den Lebenszyklus einer HTTP/3-Verbindung:

  • "Connection Setup and Management" (Verbindungsaufbau und -verwaltung) (Abschnitt 3) behandelt, wie ein HTTP/3-Endpunkt erkannt und eine HTTP/3-Verbindung hergestellt wird.

  • "Expressing HTTP Semantics in HTTP/3" (HTTP-Semantik in HTTP/3 ausdrücken) (Abschnitt 4) beschreibt, wie HTTP-Semantik mithilfe von Frames ausgedrückt wird.

  • "Connection Closure" (Verbindungsabschluss) (Abschnitt 5) beschreibt, wie HTTP/3-Verbindungen entweder ordnungsgemäß oder abrupt beendet werden.

Die Details des Drahtprotokolls (Wire Protocol) und die Interaktionen mit dem Transport werden in nachfolgenden Abschnitten beschrieben:

  • "Stream Mapping and Usage" (Stream-Zuordnung und -Verwendung) (Abschnitt 6) beschreibt die Art und Weise, wie QUIC-Streams verwendet werden.

  • "HTTP Framing Layer" (HTTP-Framing-Schicht) (Abschnitt 7) beschreibt die Frames, die auf den meisten Streams verwendet werden.

  • "Error Handling" (Fehlerbehandlung) (Abschnitt 8) beschreibt, wie Fehlerbedingungen behandelt und ausgedrückt werden, entweder auf einem bestimmten Stream oder für die Verbindung als Ganzes.

Zusätzliche Ressourcen werden in den abschließenden Abschnitten bereitgestellt:

  • "Extensions to HTTP/3" (Erweiterungen zu HTTP/3) (Abschnitt 9) beschreibt, wie neue Funktionen in zukünftigen Dokumenten hinzugefügt werden können.

  • Ein detaillierterer Vergleich zwischen HTTP/2 und HTTP/3 findet sich in Anhang A.

2.2. Conventions and Terminology (Konventionen und Terminologie)​

Die Schlüsselwörter "MUST" (muss), "MUST NOT" (darf nicht), "REQUIRED" (erforderlich), "SHALL" (muss), "SHALL NOT" (darf nicht), "SHOULD" (sollte), "SHOULD NOT" (sollte nicht), "RECOMMENDED" (empfohlen), "NOT RECOMMENDED" (nicht empfohlen), "MAY" (kann) und "OPTIONAL" (optional) in diesem Dokument sind wie in BCP 14 [RFC2119] [RFC8174] beschrieben zu interpretieren, wenn und nur wenn sie in Großbuchstaben erscheinen, wie hier gezeigt.

Dieses Dokument verwendet die Kodierung von Ganzzahlen variabler Länge (Variable-Length Integer Encoding) aus [QUIC-TRANSPORT].

Die folgenden Begriffe werden verwendet:

abort (Abbruch): Eine abrupte Beendigung einer Verbindung oder eines Streams, möglicherweise aufgrund einer Fehlerbedingung.

client (Client): Der Endpunkt, der eine HTTP/3-Verbindung initiiert. Clients senden HTTP-Anfragen und empfangen HTTP-Antworten.

connection (Verbindung): Eine Transportschichtverbindung zwischen zwei Endpunkten, die QUIC als Transportprotokoll verwendet.

connection error (Verbindungsfehler): Ein Fehler, der die gesamte HTTP/3-Verbindung betrifft.

endpoint (Endpunkt): Entweder der Client oder der Server der Verbindung.

frame (Frame): Die kleinste Kommunikationseinheit auf einem Stream in HTTP/3, bestehend aus einem Header und einer Bytesequenz variabler Länge, die entsprechend dem Frame-Typ strukturiert ist.

Protokollelemente, die "Frames" genannt werden, existieren sowohl in diesem Dokument als auch in [QUIC-TRANSPORT]. Wenn auf Frames aus [QUIC-TRANSPORT] verwiesen wird, wird dem Frame-Namen "QUIC" vorangestellt. Zum Beispiel "QUIC CONNECTION_CLOSE frames". Verweise ohne dieses Präfix beziehen sich auf Frames, die in Abschnitt 7.2 definiert sind.

HTTP/3 connection (HTTP/3-Verbindung): Eine QUIC-Verbindung, bei der das ausgehandelte Anwendungsprotokoll HTTP/3 ist.

peer (Peer): Ein Endpunkt. Bei der Diskussion eines bestimmten Endpunkts bezieht sich "peer" auf den Endpunkt, der vom Hauptthema der Diskussion entfernt ist.

receiver (Empfänger): Ein Endpunkt, der Frames empfängt.

sender (Sender): Ein Endpunkt, der Frames überträgt.

server (Server): Der Endpunkt, der eine HTTP/3-Verbindung akzeptiert. Server empfangen HTTP-Anfragen und senden HTTP-Antworten.

stream (Stream): Ein bidirektionaler oder unidirektionaler Bytestrom (Bytestream), der vom QUIC-Transport bereitgestellt wird. Alle Streams innerhalb einer HTTP/3-Verbindung können als "HTTP/3-Streams" betrachtet werden, aber innerhalb von HTTP/3 sind mehrere Stream-Typen definiert.

stream error (Stream-Fehler): Ein Fehler auf Anwendungsebene auf dem einzelnen Stream.

Der Begriff "content" (Inhalt) ist in Abschnitt 6.4 von [HTTP] definiert.

Schließlich sind die Begriffe "resource" (Ressource), "message" (Nachricht), "user agent" (Benutzeragent), "origin server" (Ursprungsserver), "gateway" (Gateway), "intermediary" (Vermittler), "proxy" (Proxy) und "tunnel" (Tunnel) in Abschnitt 3 von [HTTP] definiert.

Paketdiagramme (Packet Diagrams) in diesem Dokument verwenden das in Abschnitt 1.3 von [QUIC-TRANSPORT] definierte Format, um die Reihenfolge und Größe von Feldern zu veranschaulichen.



3. Connection Setup and Management (Verbindungsaufbau und -verwaltung)​

3.1. Discovering an HTTP/3 Endpoint (Erkennung eines HTTP/3-Endpunkts)​

HTTP basiert auf dem Konzept einer autoritativen Antwort (Authoritative Response): eine Antwort, die als die am besten geeignete Antwort für diese Anfrage bestimmt wurde, gegeben den Zustand der Zielressource zum Zeitpunkt der Entstehung der Antwortnachricht durch (oder unter Anweisung von) dem Ursprungsserver (Origin Server), der innerhalb der Ziel-URI identifiziert wird. Die Lokalisierung eines autoritativen Servers für eine HTTP-URI wird in Abschnitt 4.3 von [HTTP] besprochen.

Das "https"-Schema verbindet Autorität mit dem Besitz eines Zertifikats, das der Client für den durch die Autoritätskomponente (Authority Component) der URI identifizierten Host als vertrauenswürdig erachtet. Nach Empfang eines Serverzertifikats im TLS-Handshake muss (MUST) der Client überprüfen, dass das Zertifikat eine akzeptable Übereinstimmung für den Ursprungsserver der URI ist, unter Verwendung des in Abschnitt 4.3.4 von [HTTP] beschriebenen Prozesses. Wenn das Zertifikat nicht in Bezug auf den Ursprungsserver der URI verifiziert werden kann, darf (MUST NOT) der Client den Server nicht als autoritativ für diesen Ursprung betrachten.

Ein Client kann (MAY) versuchen, auf eine Ressource mit einer "https"-URI zuzugreifen, indem er die Host-Kennung in eine IP-Adresse auflöst, eine QUIC-Verbindung zu dieser Adresse am angegebenen Port herstellt (einschließlich der Validierung des Serverzertifikats wie oben beschrieben) und eine HTTP/3-Anfragenachricht sendet, die auf die URI abzielt, über diese gesicherte Verbindung an den Server. Sofern kein anderer Mechanismus zur Auswahl von HTTP/3 verwendet wird, wird das Token "h3" in der ALPN-Erweiterung (Application-Layer Protocol Negotiation; siehe [RFC7301]) während des TLS-Handshakes verwendet.

Verbindungsprobleme (z. B. Blockieren von UDP) können zu einem Fehler beim Herstellen einer QUIC-Verbindung führen; Clients sollten (SHOULD) in diesem Fall versuchen, TCP-basierte Versionen von HTTP zu verwenden.

Server können (MAY) HTTP/3 auf jedem UDP-Port bereitstellen; eine Alternative Service Advertisement enthält immer einen expliziten Port, und URIs enthalten entweder einen expliziten Port oder einen mit dem Schema verbundenen Standardport.

3.1.1. HTTP Alternative Services (HTTP-Alternative Dienste)​

Ein HTTP-Ursprung kann die Verfügbarkeit eines äquivalenten HTTP/3-Endpunkts über das Alt-Svc HTTP-Antwort-Header-Feld oder den HTTP/2 ALTSVC-Frame ([ALTSVC]) unter Verwendung des "h3" ALPN-Tokens ankündigen.

Beispielsweise könnte ein Ursprung in einer HTTP-Antwort angeben, dass HTTP/3 auf UDP-Port 50781 am selben Hostnamen verfügbar war, indem das folgende Header-Feld eingeschlossen wird:

Alt-Svc: h3=":50781"

Nach Erhalt eines Alt-Svc-Eintrags, der HTTP/3-Unterstützung anzeigt, kann (MAY) ein Client versuchen, eine QUIC-Verbindung zum angegebenen Host und Port herzustellen; wenn diese Verbindung erfolgreich ist, kann der Client HTTP-Anfragen unter Verwendung der in diesem Dokument beschriebenen Zuordnung senden.

3.1.2. Other Schemes (Andere Schemata)​

Obwohl HTTP vom Transportprotokoll unabhängig ist, verbindet das "http"-Schema Autorität mit der Fähigkeit, TCP-Verbindungen am angegebenen Port des Hosts zu empfangen, der innerhalb der Autoritätskomponente identifiziert wird. Da HTTP/3 kein TCP verwendet, kann HTTP/3 nicht für den direkten Zugriff auf den autoritativen Server für eine durch eine "http"-URI identifizierte Ressource verwendet werden. Protokollerweiterungen wie [ALTSVC] erlauben es dem autoritativen Server jedoch, andere Dienste zu identifizieren, die ebenfalls autoritativ sind und möglicherweise über HTTP/3 erreichbar sind.

Bevor Anfragen für einen Ursprung gestellt werden, dessen Schema nicht "https" ist, muss (MUST) der Client sicherstellen, dass der Server bereit ist, dieses Schema zu bedienen. Für Ursprünge, deren Schema "http" ist, wird eine experimentelle Methode zur Erreichung dessen in [RFC8164] beschrieben. Andere Mechanismen könnten in Zukunft für verschiedene Schemata definiert werden.

3.2. Connection Establishment (Verbindungsherstellung)​

HTTP/3 basiert auf QUIC Version 1 als zugrunde liegendem Transport. Die Verwendung anderer QUIC-Transportversionen mit HTTP/3 kann (MAY) durch zukünftige Spezifikationen definiert werden.

QUIC Version 1 verwendet TLS Version 1.3 oder höher als Handshake-Protokoll (Handshake Protocol). HTTP/3-Clients müssen (MUST) einen Mechanismus unterstützen, um den Zielhost während des TLS-Handshakes dem Server anzuzeigen. Wenn der Server durch einen Domainnamen ([DNS-TERMS]) identifiziert wird, müssen (MUST) Clients die Server Name Indication (SNI; [RFC6066]) TLS-Erweiterung senden, es sei denn, es wird ein alternativer Mechanismus zur Angabe des Zielhosts verwendet.

QUIC-Verbindungen werden wie in [QUIC-TRANSPORT] beschrieben hergestellt. Während der Verbindungsherstellung wird HTTP/3-Unterstützung durch Auswahl des ALPN-Tokens "h3" im TLS-Handshake angezeigt. Unterstützung für andere Anwendungsschichtprotokolle kann (MAY) im selben Handshake angeboten werden.

Während Optionen auf Verbindungsebene, die das Kern-QUIC-Protokoll betreffen, im anfänglichen Krypto-Handshake festgelegt werden, werden HTTP/3-spezifische Einstellungen im SETTINGS-Frame übermittelt. Nach der Herstellung der QUIC-Verbindung muss (MUST) von jedem Endpunkt ein SETTINGS-Frame als anfänglicher Frame seines jeweiligen HTTP-Kontrollstreams (HTTP Control Stream) gesendet werden.

3.3. Connection Reuse (Verbindungswiederverwendung)​

HTTP/3-Verbindungen sind über mehrere Anfragen hinweg persistent. Für beste Leistung wird erwartet, dass Clients Verbindungen nicht schließen, bis festgestellt wird, dass keine weitere Kommunikation mit einem Server erforderlich ist (z. B. wenn ein Benutzer von einer bestimmten Webseite wegnavigiert) oder bis der Server die Verbindung schließt.

Sobald eine Verbindung zu einem Server-Endpunkt besteht, kann (MAY) diese Verbindung für Anfragen mit mehreren unterschiedlichen URI-Autoritätskomponenten wiederverwendet werden. Um eine bestehende Verbindung für einen neuen Ursprung zu verwenden, müssen (MUST) Clients das vom Server für den neuen Ursprungsserver präsentierte Zertifikat unter Verwendung des in Abschnitt 4.3.4 von [HTTP] beschriebenen Prozesses validieren. Dies impliziert, dass Clients das Serverzertifikat und alle zusätzlichen Informationen, die zur Verifizierung dieses Zertifikats benötigt werden, behalten müssen; Clients, die dies nicht tun, können die Verbindung nicht für zusätzliche Ursprünge wiederverwenden.

Wenn das Zertifikat aus irgendeinem Grund in Bezug auf den neuen Ursprung nicht akzeptabel ist, darf (MUST NOT) die Verbindung nicht wiederverwendet werden, und es sollte (SHOULD) eine neue Verbindung für den neuen Ursprung hergestellt werden. Wenn der Grund, warum das Zertifikat nicht verifiziert werden kann, auf andere bereits mit der Verbindung verbundene Ursprünge zutreffen könnte, sollte (SHOULD) der Client das Serverzertifikat für diese Ursprünge erneut validieren. Wenn beispielsweise die Validierung eines Zertifikats fehlschlägt, weil das Zertifikat abgelaufen oder widerrufen wurde, könnte dies verwendet werden, um alle anderen Ursprünge zu invalidieren, für die dieses Zertifikat zur Feststellung der Autorität verwendet wurde.

Clients sollten (SHOULD NOT) nicht mehr als eine HTTP/3-Verbindung zu einer gegebenen IP-Adresse und einem UDP-Port öffnen, wobei die IP-Adresse und der Port von einer URI, einem ausgewählten alternativen Dienst ([ALTSVC]), einem konfigurierten Proxy oder der Namensauflösung eines dieser Elemente abgeleitet werden können. Ein Client kann (MAY) mehrere HTTP/3-Verbindungen zur selben IP-Adresse und zum selben UDP-Port unter Verwendung unterschiedlicher Transport- oder TLS-Konfigurationen öffnen, sollte (SHOULD) jedoch vermeiden, mehrere Verbindungen mit derselben Konfiguration zu erstellen.

Server werden ermutigt, offene HTTP/3-Verbindungen so lange wie möglich aufrechtzuerhalten, sind aber berechtigt, inaktive Verbindungen (Idle Connections) bei Bedarf zu beenden. Wenn einer der Endpunkte wählt, die HTTP/3-Verbindung zu schließen, sollte (SHOULD) der beendende Endpunkt zuerst einen GOAWAY-Frame (Abschnitt 5.2) senden, damit beide Endpunkte zuverlässig bestimmen können, ob zuvor gesendete Frames verarbeitet wurden, und alle notwendigen verbleibenden Aufgaben ordnungsgemäß abschließen oder beenden können.

Ein Server, der nicht möchte, dass Clients HTTP/3-Verbindungen für einen bestimmten Ursprung wiederverwenden, kann anzeigen, dass er für eine Anfrage nicht autoritativ ist, indem er einen 421-Statuscode (Misdirected Request, Fehlgeleitete Anfrage) als Antwort auf die Anfrage sendet; siehe Abschnitt 7.4 von [HTTP].



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:

  1. dem Header-Abschnitt (Header Section), einschließlich Nachrichtensteuerungsdaten, gesendet als einzelner HEADERS-Frame,

  2. optional dem Inhalt (Content), falls vorhanden, gesendet als eine Reihe von DATA-Frames, und

  3. 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.


5. Verbindungsschluss (Connection Closure)​

Einmal hergestellt, kann eine HTTP/3-Verbindung im Laufe der Zeit für viele Anfragen und Antworten verwendet werden, bis die Verbindung geschlossen wird. Der Verbindungsschluss kann auf verschiedene Weise erfolgen.

5.1. Leerlaufende Verbindungen (Idle Connections)​

Jeder QUIC-Endpunkt deklariert während des Handshakes einen Leerlauf-Timeout (Idle Timeout). Wenn die QUIC-Verbindung länger als diese Dauer im Leerlauf bleibt (keine Pakete empfangen werden), nimmt der Peer an, dass die Verbindung geschlossen wurde. HTTP/3-Implementierungen müssen eine neue HTTP/3-Verbindung für neue Anfragen öffnen, wenn die vorhandene Verbindung länger im Leerlauf war als der während des QUIC-Handshakes ausgehandelte Leerlauf-Timeout, und sie SOLLTEN (SHOULD) dies tun, wenn sie sich dem Leerlauf-Timeout nähern; siehe Abschnitt 10.1 von [QUIC-TRANSPORT].

Von HTTP-Clients wird erwartet, dass sie verlangen, dass der Transport Verbindungen offen hält, während ausstehende Antworten auf Anfragen oder Server-Pushes vorliegen, wie in Abschnitt 10.1.2 von [QUIC-TRANSPORT] beschrieben. Wenn der Client keine Antwort vom Server erwartet, ist es vorzuziehen, eine im Leerlauf befindliche Verbindung zeitlich ablaufen zu lassen, anstatt Aufwand für die Aufrechterhaltung einer möglicherweise nicht benötigten Verbindung aufzuwenden. Ein Gateway KANN (MAY) Verbindungen in Erwartung des Bedarfs aufrechterhalten, anstatt die Latenzkosten für den Verbindungsaufbau zu Servern zu tragen. Server SOLLTEN (SHOULD NOT) Verbindungen nicht aktiv offen halten.

5.2. Verbindungsherunterfahren (Connection Shutdown)​

Auch wenn eine Verbindung nicht im Leerlauf ist, kann jeder Endpunkt entscheiden, die Verwendung der Verbindung einzustellen und einen ordnungsgemäßen Verbindungsschluss (Graceful Connection Close) einzuleiten. Endpunkte leiten das ordnungsgemäße Herunterfahren einer HTTP/3-Verbindung ein, indem sie einen GOAWAY-Frame senden. Der GOAWAY-Frame enthält eine Kennung, die dem Empfänger den Bereich der Anfragen oder Pushes anzeigt, die in dieser Verbindung verarbeitet wurden oder werden könnten. Der Server sendet eine vom Client initiierte bidirektionale Stream-ID; der Client sendet eine Push-ID. Anfragen oder Pushes mit der angegebenen Kennung oder größer werden vom Sender des GOAWAY abgelehnt (Abschnitt 4.1.1). Diese Kennung KANN (MAY) Null sein, wenn keine Anfragen oder Pushes verarbeitet wurden.

Die Informationen im GOAWAY-Frame ermöglichen es einem Client und einem Server, sich darauf zu einigen, welche Anfragen oder Pushes vor dem Herunterfahren der HTTP/3-Verbindung akzeptiert wurden. Beim Senden eines GOAWAY-Frames SOLLTE (SHOULD) der Endpunkt alle Anfragen oder Pushes, die Kennungen größer oder gleich der angegebenen haben, explizit abbrechen (siehe Abschnitte 4.1.1 und 7.2.3), um den Transportzustand für die betroffenen Streams zu bereinigen. Der Endpunkt SOLLTE (SHOULD) dies weiterhin tun, wenn weitere Anfragen oder Pushes eintreffen.

Endpunkte DÜRFEN (MUST NOT) nach Empfang eines GOAWAY-Frames vom Peer keine neuen Anfragen initiieren oder neue Pushes versprechen. Clients KÖNNEN (MAY) eine neue Verbindung herstellen, um zusätzliche Anfragen zu senden.

Einige Anfragen oder Pushes könnten bereits unterwegs sein:

  • Beim Empfang eines GOAWAY-Frames, wenn der Client bereits Anfragen mit einer Stream-ID gesendet hat, die größer oder gleich der im GOAWAY-Frame enthaltenen Kennung ist, werden diese Anfragen nicht verarbeitet. Clients können nicht verarbeitete Anfragen sicher auf einer anderen HTTP-Verbindung wiederholen. Ein Client, der Anfragen nicht wiederholen kann, verliert alle Anfragen, die während des Schließens der Verbindung durch den Server übertragen werden.

    Anfragen auf Stream-IDs, die kleiner sind als die Stream-ID in einem GOAWAY-Frame vom Server, könnten verarbeitet worden sein; ihr Status kann erst bekannt sein, wenn eine Antwort empfangen wird, der Stream einzeln zurückgesetzt wird, ein weiterer GOAWAY mit einer niedrigeren Stream-ID als die der fraglichen Anfrage empfangen wird oder die Verbindung beendet wird.

    Server KÖNNEN (MAY) einzelne Anfragen auf Streams unterhalb der angegebenen ID ablehnen, wenn diese Anfragen nicht verarbeitet wurden.

  • Wenn ein Server einen GOAWAY-Frame erhält, nachdem er Pushes mit einer Push-ID versprochen hat, die größer oder gleich der im GOAWAY-Frame enthaltenen Kennung ist, werden diese Pushes nicht akzeptiert.

Server SOLLTEN (SHOULD) einen GOAWAY-Frame senden, wenn das Schließen einer Verbindung im Voraus bekannt ist, auch wenn die Vorankündigung gering ist, damit der entfernte Peer wissen kann, ob eine Anfrage teilweise verarbeitet wurde oder nicht. Wenn beispielsweise ein HTTP-Client einen POST sendet, während ein Server gleichzeitig eine QUIC-Verbindung schließt, kann der Client nicht wissen, ob der Server mit der Verarbeitung dieser POST-Anfrage begonnen hat, wenn der Server keinen GOAWAY-Frame sendet, um anzuzeigen, auf welche Streams er möglicherweise eingewirkt hat.

Ein Endpunkt KANN (MAY) mehrere GOAWAY-Frames senden, die verschiedene Kennungen anzeigen, aber die Kennung in jedem Frame DARF (MUST NOT) nicht größer sein als die Kennung in einem vorherigen Frame, da Clients möglicherweise bereits nicht verarbeitete Anfragen auf einer anderen HTTP-Verbindung wiederholt haben. Der Empfang eines GOAWAY, das eine größere Kennung als zuvor empfangen enthält, MUSS (MUST) als Verbindungsfehler vom Typ H3_ID_ERROR behandelt werden.

Ein Endpunkt, der versucht, eine Verbindung ordnungsgemäß herunterzufahren, kann einen GOAWAY-Frame mit einem Wert senden, der auf den maximal möglichen Wert gesetzt ist (2^62-4 für Server, 2^62-1 für Clients). Dies stellt sicher, dass der Peer aufhört, neue Anfragen oder Pushes zu erstellen. Nachdem Zeit für ankommende Anfragen oder Pushes gelassen wurde, kann der Endpunkt einen weiteren GOAWAY-Frame senden, der anzeigt, welche Anfragen oder Pushes er vor dem Ende der Verbindung akzeptieren könnte. Dies stellt sicher, dass eine Verbindung sauber heruntergefahren werden kann, ohne Anfragen zu verlieren.

Ein Client hat mehr Flexibilität bei dem Wert, den er für das Push-ID-Feld in einem GOAWAY wählt, das er sendet. Ein Wert von 2^62-1 zeigt an, dass der Server mit der Erfüllung bereits versprochener Pushes fortfahren kann. Ein kleinerer Wert zeigt an, dass der Client Pushes mit Push-IDs größer oder gleich diesem Wert ablehnen wird. Wie der Server KANN (MAY) der Client nachfolgende GOAWAY-Frames senden, solange die angegebene Push-ID nicht größer ist als ein zuvor gesendeter Wert.

Auch wenn ein GOAWAY anzeigt, dass eine bestimmte Anfrage oder ein bestimmter Push beim Empfang nicht verarbeitet oder akzeptiert wird, existieren die zugrunde liegenden Transportressourcen weiterhin. Der Endpunkt, der diese Anfragen initiiert hat, kann sie abbrechen, um den Transportzustand zu bereinigen.

Sobald alle akzeptierten Anfragen und Pushes verarbeitet wurden, kann der Endpunkt zulassen, dass die Verbindung im Leerlauf bleibt, oder er KANN (MAY) einen sofortigen Abschluss der Verbindung einleiten. Ein Endpunkt, der ein ordnungsgemäßes Herunterfahren abschließt, SOLLTE (SHOULD) den Fehlercode H3_NO_ERROR beim Schließen der Verbindung verwenden.

Wenn ein Client alle verfügbaren bidirektionalen Stream-IDs mit Anfragen verbraucht hat, muss der Server keinen GOAWAY-Frame senden, da der Client keine weiteren Anfragen stellen kann.

5.3. Sofortiger Anwendungsschluss (Immediate Application Closure)​

Eine HTTP/3-Implementierung kann die QUIC-Verbindung jederzeit sofort schließen. Dies führt dazu, dass ein QUIC CONNECTION_CLOSE-Frame an den Peer gesendet wird, der anzeigt, dass die Anwendungsschicht die Verbindung beendet hat. Der Anwendungsfehlercode in diesem Frame zeigt dem Peer an, warum die Verbindung geschlossen wird. Siehe Abschnitt 8 für Fehlercodes, die beim Schließen einer Verbindung in HTTP/3 verwendet werden können.

Vor dem Schließen der Verbindung KANN (MAY) ein GOAWAY-Frame gesendet werden, um dem Client das Wiederholen einiger Anfragen zu ermöglichen. Das Einbeziehen des GOAWAY-Frames in dasselbe Paket wie der QUIC CONNECTION_CLOSE-Frame verbessert die Chancen, dass der Frame von Clients empfangen wird.

Wenn offene Streams vorhanden sind, die nicht explizit geschlossen wurden, werden sie implizit geschlossen, wenn die Verbindung geschlossen wird; siehe Abschnitt 10.2 von [QUIC-TRANSPORT].

5.4. Transportschluss (Transport Closure)​

Aus verschiedenen Gründen könnte der QUIC-Transport der Anwendungsschicht anzeigen, dass die Verbindung beendet wurde. Dies könnte auf einen expliziten Abschluss durch den Peer, einen Fehler auf Transportebene oder eine Änderung der Netzwerktopologie zurückzuführen sein, die die Konnektivität unterbricht.

Wenn eine Verbindung ohne GOAWAY-Frame beendet wird, MÜSSEN (MUST) Clients annehmen, dass jede gesendete Anfrage, ob ganz oder teilweise, möglicherweise verarbeitet wurde.


6. Stream-Zuordnung und -Verwendung (Stream Mapping and Usage)​

Ein QUIC-Stream bietet eine zuverlässige geordnete Bereitstellung von Bytes, garantiert jedoch keine Reihenfolge der Bereitstellung in Bezug auf Bytes auf anderen Streams. In Version 1 von QUIC werden die Stream-Daten, die HTTP-Frames enthalten, von QUIC STREAM-Frames getragen, aber diese Rahmung ist für die HTTP-Rahmungsschicht unsichtbar. Die Transportschicht puffert und ordnet empfangene Stream-Daten und stellt der Anwendung einen zuverlässigen Byte-Stream zur Verfügung. Obwohl QUIC eine ungeordnete Bereitstellung innerhalb eines Streams erlaubt, nutzt HTTP/3 diese Funktion nicht.

QUIC-Streams können entweder unidirektional sein und Daten nur vom Initiator zum Empfänger übertragen, oder bidirektional sein und Daten in beide Richtungen übertragen. Streams können entweder vom Client oder vom Server initiiert werden. Weitere Details zu QUIC-Streams finden Sie in Abschnitt 2 von [QUIC-TRANSPORT].

Wenn HTTP-Felder und -Daten über QUIC gesendet werden, übernimmt die QUIC-Schicht den größten Teil der Stream-Verwaltung. HTTP muss bei Verwendung von QUIC kein separates Multiplexing durchführen: Daten, die über einen QUIC-Stream gesendet werden, werden immer auf eine bestimmte HTTP-Transaktion oder auf den gesamten HTTP/3-Verbindungskontext abgebildet.

6.1. Bidirektionale Streams (Bidirectional Streams)​

Alle vom Client initiierten bidirektionalen Streams werden für HTTP-Anfragen und -Antworten verwendet. Ein bidirektionaler Stream stellt sicher, dass die Antwort leicht mit der Anfrage korreliert werden kann. Diese Streams werden als Anforderungsstreams (Request Streams) bezeichnet.

Dies bedeutet, dass die erste Anfrage des Clients auf QUIC-Stream 0 erfolgt, mit nachfolgenden Anfragen auf den Streams 4, 8 usw. Um das Öffnen dieser Streams zu ermöglichen, SOLLTE (SHOULD) ein HTTP/3-Server von Null verschiedene Mindestwerte für die Anzahl der zulässigen Streams und das anfängliche Stream-Flusskontrollfenster konfigurieren. Um die Parallelität nicht unnötig einzuschränken, SOLLTEN (SHOULD) mindestens 100 Anforderungsstreams gleichzeitig zugelassen werden.

HTTP/3 verwendet keine vom Server initiierten bidirektionalen Streams, obwohl eine Erweiterung eine Verwendung für diese Streams definieren könnte. Clients MÜSSEN (MUST) den Empfang eines vom Server initiierten bidirektionalen Streams als Verbindungsfehler vom Typ H3_STREAM_CREATION_ERROR behandeln, es sei denn, eine solche Erweiterung wurde ausgehandelt.

6.2. Unidirektionale Streams (Unidirectional Streams)​

Unidirektionale Streams in beide Richtungen werden für eine Reihe von Zwecken verwendet. Der Zweck wird durch einen Stream-Typ (Stream Type) angezeigt, der als Integer mit variabler Länge am Anfang des Streams gesendet wird. Das Format und die Struktur der Daten, die diesem Integer folgen, werden durch den Stream-Typ bestimmt.

Unidirectional Stream Header {
Stream Type (i),
}

Abbildung 1: Unidirektionaler Stream-Header

In diesem Dokument sind zwei Stream-Typen definiert: Steuerungsstreams (Control Streams) (Abschnitt 6.2.1) und Push-Streams (Push Streams) (Abschnitt 6.2.2). [QPACK] definiert zwei zusätzliche Stream-Typen. Andere Stream-Typen können durch Erweiterungen zu HTTP/3 definiert werden; siehe Abschnitt 9 für weitere Details. Einige Stream-Typen sind reserviert (Abschnitt 6.2.3).

Die Leistung von HTTP/3-Verbindungen in der frühen Phase ihrer Lebensdauer ist empfindlich gegenüber der Erstellung und dem Austausch von Daten auf unidirektionalen Streams. Endpunkte, die die Anzahl der Streams oder das Flusskontrollfenster dieser Streams übermäßig einschränken, erhöhen die Wahrscheinlichkeit, dass der entfernte Peer frühzeitig das Limit erreicht und blockiert wird. Insbesondere sollten Implementierungen berücksichtigen, dass entfernte Peers möglicherweise mit einigen der unidirektionalen Streams, die sie verwenden dürfen, das reservierte Stream-Verhalten (Abschnitt 6.2.3) ausüben möchten.

Jeder Endpunkt muss mindestens einen unidirektionalen Stream für den HTTP-Steuerungsstream erstellen. QPACK erfordert zwei zusätzliche unidirektionale Streams, und andere Erweiterungen könnten weitere Streams erfordern. Daher MÜSSEN (MUST) die von Clients und Servern gesendeten Transportparameter dem Peer erlauben, mindestens drei unidirektionale Streams zu erstellen. Diese Transportparameter SOLLTEN (SHOULD) auch jedem unidirektionalen Stream mindestens 1.024 Bytes Flusskontroll-Guthaben zur Verfügung stellen.

Beachten Sie, dass ein Endpunkt nicht verpflichtet ist, zusätzliche Guthaben zu gewähren, um mehr unidirektionale Streams zu erstellen, wenn sein Peer alle anfänglichen Guthaben verbraucht, bevor er die kritischen unidirektionalen Streams erstellt. Endpunkte SOLLTEN (SHOULD) zuerst den HTTP-Steuerungsstream sowie die durch obligatorische Erweiterungen (wie die QPACK-Encoder- und Decoder-Streams) erforderlichen unidirektionalen Streams erstellen und dann zusätzliche Streams erstellen, wie es ihr Peer zulässt.

Wenn der Stream-Header einen Stream-Typ anzeigt, der vom Empfänger nicht unterstützt wird, kann der Rest des Streams nicht verarbeitet werden, da die Semantik unbekannt ist. Empfänger unbekannter Stream-Typen MÜSSEN (MUST) entweder das Lesen des Streams abbrechen oder eingehende Daten ohne weitere Verarbeitung verwerfen. Wenn das Lesen abgebrochen wird, SOLLTE (SHOULD) der Empfänger den Fehlercode H3_STREAM_CREATION_ERROR oder einen reservierten Fehlercode (Abschnitt 8.1) verwenden. Der Empfänger DARF (MUST NOT) unbekannte Stream-Typen nicht als Verbindungsfehler irgendeiner Art betrachten.

Da bestimmte Stream-Typen den Verbindungszustand beeinflussen können, SOLLTE (SHOULD NOT) ein Empfänger Daten von eingehenden unidirektionalen Streams nicht verwerfen, bevor er den Stream-Typ gelesen hat.

Implementierungen KÖNNEN (MAY) Stream-Typen senden, bevor sie wissen, ob der Peer sie unterstützt. Stream-Typen, die den Zustand oder die Semantik vorhandener Protokollkomponenten ändern könnten, einschließlich QPACK oder anderer Erweiterungen, DÜRFEN (MUST NOT) jedoch nicht gesendet werden, bis bekannt ist, dass der Peer sie unterstützt.

Ein Sender kann einen unidirektionalen Stream schließen oder zurücksetzen, sofern nicht anders angegeben. Ein Empfänger MUSS (MUST) tolerieren, dass unidirektionale Streams vor dem Empfang des unidirektionalen Stream-Headers geschlossen oder zurückgesetzt werden.

6.2.1. Steuerungsstreams (Control Streams)​

Ein Steuerungsstream wird durch einen Stream-Typ von 0x00 angezeigt. Daten auf diesem Stream bestehen aus HTTP/3-Frames, wie in Abschnitt 7.2 definiert.

Jede Seite MUSS (MUST) zu Beginn der Verbindung einen einzelnen Steuerungsstream initiieren und ihren SETTINGS-Frame als ersten Frame auf diesem Stream senden. Wenn der erste Frame des Steuerungsstreams ein anderer Frame-Typ ist, MUSS (MUST) dies als Verbindungsfehler vom Typ H3_MISSING_SETTINGS behandelt werden. Pro Peer ist nur ein Steuerungsstream zulässig; der Empfang eines zweiten Streams, der behauptet, ein Steuerungsstream zu sein, MUSS (MUST) als Verbindungsfehler vom Typ H3_STREAM_CREATION_ERROR behandelt werden. Der Sender DARF (MUST NOT) den Steuerungsstream nicht schließen, und der Empfänger DARF (MUST NOT) nicht verlangen, dass der Sender den Steuerungsstream schließt. Wenn einer der Steuerungsstreams zu irgendeinem Zeitpunkt geschlossen wird, MUSS (MUST) dies als Verbindungsfehler vom Typ H3_CLOSED_CRITICAL_STREAM behandelt werden. Verbindungsfehler werden in Abschnitt 8 beschrieben.

Da der Inhalt des Steuerungsstreams zur Verwaltung des Verhaltens anderer Streams verwendet wird, SOLLTEN (SHOULD) Endpunkte genügend Flusskontroll-Guthaben bereitstellen, um zu verhindern, dass der Steuerungsstream des Peers blockiert wird.

Anstelle eines einzelnen bidirektionalen Streams wird ein Paar unidirektionaler Streams verwendet. Dies ermöglicht es jedem Peer, Daten zu senden, sobald er dazu in der Lage ist. Je nachdem, ob 0-RTT auf der QUIC-Verbindung verfügbar ist, können entweder Client oder Server möglicherweise zuerst Stream-Daten senden.

6.2.2. Push-Streams (Push Streams)​

Server-Push (Server Push) ist eine in HTTP/2 eingeführte optionale Funktion, die es einem Server ermöglicht, eine Antwort zu initiieren, bevor eine Anfrage gestellt wurde. Weitere Details finden Sie in Abschnitt 4.4.

Ein Push-Stream wird durch einen Stream-Typ von 0x01 angezeigt, gefolgt von der Push-ID (Push ID) des Versprechens, das er erfüllt, codiert als Integer mit variabler Länge. Die verbleibenden Daten auf diesem Stream bestehen aus HTTP/3-Frames, wie in Abschnitt 7.2 definiert, und erfüllen einen versprochenen Server-Push durch null oder mehr vorläufige HTTP-Antworten, gefolgt von einer einzelnen endgültigen HTTP-Antwort, wie in Abschnitt 4.1 definiert. Server-Push und Push-IDs werden in Abschnitt 4.6 beschrieben.

Nur Server können pushen; wenn ein Server einen vom Client initiierten Push-Stream erhält, MUSS (MUST) dies als Verbindungsfehler vom Typ H3_STREAM_CREATION_ERROR behandelt werden.

Push Stream Header {
Stream Type (i) = 0x01,
Push ID (i),
}

Abbildung 2: Push-Stream-Header

Ein Client SOLLTE (SHOULD NOT) das Lesen eines Push-Streams nicht abbrechen, bevor er den Push-Stream-Header gelesen hat, da dies zu Unstimmigkeiten zwischen Client und Server darüber führen könnte, welche Push-IDs bereits verbraucht wurden.

Jede Push-ID DARF (MUST) in einem Push-Stream-Header nur einmal verwendet werden. Wenn ein Client erkennt, dass ein Push-Stream-Header eine Push-ID enthält, die in einem anderen Push-Stream-Header verwendet wurde, MUSS (MUST) der Client dies als Verbindungsfehler vom Typ H3_ID_ERROR behandeln.

6.2.3. Reservierte Stream-Typen (Reserved Stream Types)​

Stream-Typen im Format 0x1f * N + 0x21 für nicht-negative ganzzahlige Werte von N sind reserviert, um die Anforderung auszuüben, dass unbekannte Typen ignoriert werden. Diese Streams haben keine Semantik, und sie können gesendet werden, wenn Padding auf Anwendungsebene gewünscht wird. Sie KÖNNEN (MAY) auch auf Verbindungen gesendet werden, auf denen derzeit keine Daten übertragen werden. Endpunkte DÜRFEN (MUST NOT) beim Empfang nicht davon ausgehen, dass diese Streams eine Bedeutung haben.

Die Nutzlast und Länge des Streams werden auf beliebige Weise ausgewählt, die die sendende Implementierung wählt. Beim Senden eines reservierten Stream-Typs KANN (MAY) die Implementierung den Stream entweder sauber beenden oder zurücksetzen. Beim Zurücksetzen des Streams SOLLTE (SHOULD) entweder der Fehlercode H3_NO_ERROR oder ein reservierter Fehlercode (Abschnitt 8.1) verwendet werden.


7. HTTP-Framing-Schicht (HTTP Framing Layer)​

HTTP-Frames werden auf QUIC-Streams übertragen, wie in Abschnitt 6 beschrieben. HTTP/3 definiert drei Stream-Typen: Kontrollstream, Anfrage-Stream und Push-Stream. Dieser Abschnitt beschreibt HTTP/3-Frame-Formate und ihre zulässigen Stream-Typen; siehe Tabelle 1 für eine Übersicht.

Tabelle 1: Übersicht über HTTP/3-Frames und Stream-Typen

FrameKontrollstreamAnfrage-StreamPush-StreamAbschnitt
DATANeinJaJa7.2.1
HEADERSNeinJaJa7.2.2
CANCEL_PUSHJaNeinNein7.2.3
SETTINGSJa (1)NeinNein7.2.4
PUSH_PROMISENeinJaNein7.2.5
GOAWAYJaNeinNein7.2.6
MAX_PUSH_IDJaNeinNein7.2.7
ReserviertJaJaJa7.2.8

Der SETTINGS-Frame kann nur als erster Frame eines Kontrollstreams auftreten; dies ist in Tabelle 1 mit (1) gekennzeichnet.

Beachten Sie, dass HTTP/3-Frames im Gegensatz zu QUIC-Frames mehrere Pakete umfassen können.

7.1. Frame-Layout​

Alle Frames haben das folgende Format:

HTTP/3 Frame Format {
Type (i),
Length (i),
Frame Payload (..),
}

Ein Frame enthält die folgenden Felder:

  • Type (Typ): Eine Ganzzahl variabler Länge, die den Frame-Typ identifiziert
  • Length (Länge): Eine Ganzzahl variabler Länge, die die Länge in Bytes der Frame-Nutzlast beschreibt
  • Frame Payload (Frame-Nutzlast): Eine Nutzlast, deren Semantik durch das Type-Feld bestimmt wird

Die Nutzlast jedes Frames MUSS (MUST) genau die in seiner Beschreibung identifizierten Felder enthalten. Eine Frame-Nutzlast, die zusätzliche Bytes enthält oder vorzeitig endet, MUSS (MUST) als Verbindungsfehler vom Typ H3_FRAME_ERROR behandelt werden.

7.2. Frame-Definitionen (Frame Definitions)​

7.2.1. DATA​

DATA-Frames (type=0x00) übertragen beliebige Bytesequenzen variabler Länge, die mit HTTP-Anfrage- oder -Antwortinhalt verbunden sind.

DATA-Frames MÜSSEN (MUST) mit einer HTTP-Anfrage oder -Antwort verknüpft sein. Wenn ein DATA-Frame auf einem Kontrollstream empfangen wird, MUSS (MUST) der Empfänger mit einem Verbindungsfehler vom Typ H3_FRAME_UNEXPECTED antworten.

7.2.2. HEADERS​

Der HEADERS-Frame (type=0x01) wird verwendet, um einen mit QPACK codierten HTTP-Feldabschnitt zu übertragen.

HEADERS-Frames können nur auf Anfrage-Streams oder Push-Streams gesendet werden. Wenn ein HEADERS-Frame auf einem Kontrollstream empfangen wird, MUSS (MUST) der Empfänger mit einem Verbindungsfehler vom Typ H3_FRAME_UNEXPECTED antworten.

7.2.3. CANCEL_PUSH​

Der CANCEL_PUSH-Frame (type=0x03) wird verwendet, um die Stornierung eines Server-Pushs anzufordern, bevor der Push-Stream empfangen wird.

Wenn ein Client einen CANCEL_PUSH-Frame sendet, zeigt er an, dass er die versprochene Ressource nicht empfangen möchte. Der Server SOLLTE (SHOULD) das Senden der Ressource abbrechen.

CANCEL_PUSH-Frames werden auf dem Kontrollstream gesendet. Der Empfang eines CANCEL_PUSH-Frames auf einem Anfrage-Stream oder Push-Stream MUSS (MUST) als Verbindungsfehler vom Typ H3_FRAME_UNEXPECTED behandelt werden.

7.2.4. SETTINGS​

Der SETTINGS-Frame (type=0x04) übermittelt Konfigurationsparameter, die beeinflussen, wie Endpunkte kommunizieren.

SETTINGS-Frames MÜSSEN (MUST) als erster Frame jedes Kontrollstreams gesendet werden. SETTINGS-Frames DÜRFEN NICHT (MUST NOT) auf anderen Streams gesendet werden.

Definierte Einstellungsidentifikatoren umfassen:

  • SETTINGS_MAX_FIELD_SECTION_SIZE (0x06): Maximale Feldabschnittsgröße
  • SETTINGS_QPACK_MAX_TABLE_CAPACITY (0x01): QPACK-bezogene Einstellung
  • SETTINGS_QPACK_BLOCKED_STREAMS (0x07): QPACK-bezogene Einstellung

7.2.5. PUSH_PROMISE​

Der PUSH_PROMISE-Frame (type=0x05) wird verwendet, um einen versprochenen Anfrage-Header-Feldabschnitt vom Server zum Client auf einem Anfrage-Stream zu übertragen.

PUSH_PROMISE-Frames können nur auf Anfrage-Streams gesendet werden. Der Empfang eines PUSH_PROMISE-Frames auf einem Kontrollstream oder Push-Stream MUSS (MUST) als Verbindungsfehler vom Typ H3_FRAME_UNEXPECTED behandelt werden.

7.2.6. GOAWAY​

Der GOAWAY-Frame (type=0x07) wird verwendet, um das geordnete Herunterfahren einer Verbindung einzuleiten.

GOAWAY-Frames werden immer auf dem Kontrollstream gesendet. Der Empfang eines GOAWAY-Frames auf einem Anfrage-Stream oder Push-Stream MUSS (MUST) als Verbindungsfehler vom Typ H3_FRAME_UNEXPECTED behandelt werden.

7.2.7. MAX_PUSH_ID​

Der MAX_PUSH_ID-Frame (type=0x0d) wird von Clients verwendet, um die Anzahl der Server-Pushs zu kontrollieren, die der Server initiieren kann.

MAX_PUSH_ID-Frames werden immer auf dem Kontrollstream gesendet. Ein Server DARF NICHT (MUST NOT) einen MAX_PUSH_ID-Frame senden.

7.2.8. Reservierte Frame-Typen (Reserved Frame Types)​

Frame-Typen im Format 0x1f * N + 0x21 für nichtnegative ganzzahlige Werte von N sind reserviert, um die Anforderung zu erfüllen, dass unbekannte Typen ignoriert werden. Diese Frames haben keine Semantik und können auf jedem Stream gesendet werden.


8. Fehlerbehandlung (Error Handling)​

Wenn ein Stream nicht erfolgreich abgeschlossen werden kann, erlaubt QUIC der Anwendung, diesen Stream abrupt zu beenden (zurückzusetzen) und einen Grund zu kommunizieren; siehe Abschnitt 2.4 von [QUIC-TRANSPORT]. Dies wird als "Stream-Fehler (Stream Error)" bezeichnet. Eine HTTP/3-Implementierung kann entscheiden, einen QUIC-Stream zu schließen und den Fehlertyp zu kommunizieren. Drahtcodierungen von Fehlercodes sind in Abschnitt 8.1 definiert. Stream-Fehler unterscheiden sich von HTTP-Statuscodes, die Fehlerbedingungen anzeigen. Stream-Fehler zeigen an, dass der Absender die vollständige Anfrage oder Antwort nicht übertragen oder verarbeitet hat, während HTTP-Statuscodes das Ergebnis einer erfolgreich empfangenen Anfrage anzeigen.

Wenn eine gesamte Verbindung beendet werden muss, bietet QUIC ähnlich Mechanismen zur Kommunikation eines Grundes; siehe Abschnitt 5.3 von [QUIC-TRANSPORT]. Dies wird als "Verbindungsfehler (Connection Error)" bezeichnet. Ähnlich wie bei Stream-Fehlern kann eine HTTP/3-Implementierung eine QUIC-Verbindung beenden und den Grund unter Verwendung eines Fehlercodes aus Abschnitt 8.1 kommunizieren.

Obwohl die Gründe für das Schließen von Streams und Verbindungen "Fehler" genannt werden, weisen diese Aktionen nicht notwendigerweise auf ein Problem mit der Verbindung oder einer der Implementierungen hin. Beispielsweise kann ein Stream zurückgesetzt werden, wenn die angeforderte Ressource nicht mehr benötigt wird.

Ein Endpunkt KANN (MAY) unter bestimmten Umständen einen Stream-Fehler als Verbindungsfehler behandeln und die gesamte Verbindung als Reaktion auf eine Bedingung in einem einzelnen Stream schließen. Implementierungen müssen die Auswirkungen auf ausstehende Anfragen berücksichtigen, bevor sie diese Wahl treffen.

Da neue Fehlercodes ohne Verhandlung definiert werden können (siehe Abschnitt 9), MUSS (MUST) die Verwendung eines Fehlercodes in einem unerwarteten Kontext oder der Empfang eines unbekannten Fehlercodes als gleichwertig mit H3_NO_ERROR behandelt werden. Das Schließen eines Streams kann jedoch unabhängig vom Fehlercode andere Auswirkungen haben; siehe beispielsweise Abschnitt 4.1.

8.1. HTTP/3-Fehlercodes (HTTP/3 Error Codes)​

Die folgenden Fehlercodes sind für die Verwendung beim abrupten Beenden von Streams, beim Abbrechen des Lesens von Streams oder beim sofortigen Schließen von HTTP/3-Verbindungen definiert.

H3_NO_ERROR (0x0100)
Kein Fehler. Wird verwendet, wenn die Verbindung oder der Stream geschlossen werden muss, aber kein Fehler zu signalisieren ist.

H3_GENERAL_PROTOCOL_ERROR (0x0101)
Der Peer hat Protokollanforderungen auf eine Weise verletzt, die keinem spezifischeren Fehlercode entspricht, oder der Endpunkt lehnt die Verwendung des spezifischeren Fehlercodes ab.

H3_INTERNAL_ERROR (0x0102)
Im HTTP-Stack ist ein interner Fehler aufgetreten.

H3_STREAM_CREATION_ERROR (0x0103)
Der Endpunkt hat festgestellt, dass sein Peer einen Stream erstellt hat, den er nicht akzeptieren wird.

H3_CLOSED_CRITICAL_STREAM (0x0104)
Ein für die HTTP/3-Verbindung erforderlicher Stream wurde geschlossen oder zurückgesetzt.

H3_FRAME_UNEXPECTED (0x0105)
Es wurde ein Frame empfangen, der im aktuellen Zustand oder auf dem aktuellen Stream nicht zulässig war.

H3_FRAME_ERROR (0x0106)
Es wurde ein Frame empfangen, der die Layout-Anforderungen nicht erfüllt oder eine ungültige Größe hat.

H3_EXCESSIVE_LOAD (0x0107)
Der Endpunkt hat festgestellt, dass sein Peer ein Verhalten zeigt, das möglicherweise übermäßige Last erzeugt.

H3_ID_ERROR (0x0108)
Eine Stream-ID oder Push-ID wurde falsch verwendet, z. B. durch Überschreiten eines Limits, Reduzieren eines Limits oder Wiederverwendung.

H3_SETTINGS_ERROR (0x0109)
Ein Endpunkt hat einen Fehler in der Nutzlast eines SETTINGS-Frames erkannt.

H3_MISSING_SETTINGS (0x010a)
Am Anfang des Kontrollstreams wurde kein SETTINGS-Frame empfangen.

H3_REQUEST_REJECTED (0x010b)
Ein Server hat eine Anfrage abgelehnt, ohne Anwendungsverarbeitung durchzuführen.

H3_REQUEST_CANCELLED (0x010c)
Die Anfrage oder ihre Antwort (einschließlich gepushter Antwort) wird abgebrochen.

H3_REQUEST_INCOMPLETE (0x010d)
Der Stream des Clients wurde beendet, ohne eine vollständig geformte Anfrage zu enthalten.

H3_MESSAGE_ERROR (0x010e)
Eine HTTP-Nachricht war fehlerhaft und kann nicht verarbeitet werden.

H3_CONNECT_ERROR (0x010f)
Die als Reaktion auf eine CONNECT-Anfrage hergestellte TCP-Verbindung wurde zurückgesetzt oder abnormal geschlossen.

H3_VERSION_FALLBACK (0x0110)
Die angeforderte Operation kann nicht über HTTP/3 bereitgestellt werden. Der Peer sollte über HTTP/1.1 erneut versuchen.

Fehlercodes im Format 0x1f * N + 0x21 für nichtnegative ganzzahlige Werte von N sind reserviert, um die Anforderung zu erfüllen, dass unbekannte Fehlercodes als gleichwertig mit H3_NO_ERROR behandelt werden (Abschnitt 9). Implementierungen SOLLTEN (SHOULD) mit einer gewissen Wahrscheinlichkeit einen Fehlercode aus diesem Bereich auswählen, wenn sie H3_NO_ERROR gesendet hätten.


9. Erweiterungen zu HTTP/3 (Extensions to HTTP/3)​

HTTP/3 erlaubt die Erweiterung des Protokolls. Innerhalb der in diesem Abschnitt beschriebenen Grenzen können Protokollerweiterungen verwendet werden, um zusätzliche Dienste bereitzustellen oder jeden Aspekt des Protokolls zu ändern. Erweiterungen sind nur im Rahmen einer einzelnen HTTP/3-Verbindung wirksam.

Dies gilt für die in diesem Dokument definierten Protokollelemente. Dies hat keinen Einfluss auf die bestehenden Optionen zur Erweiterung von HTTP, wie z. B. die Definition neuer Methoden, Statuscodes oder Felder.

Erweiterungen dürfen neue Frame-Typen (Abschnitt 7.2), neue Einstellungen (Abschnitt 7.2.4.1), neue Fehlercodes (Abschnitt 8) oder neue unidirektionale Stream-Typen (Abschnitt 6.2) verwenden. Register werden zur Verwaltung dieser Erweiterungspunkte eingerichtet: Frame-Typen (Abschnitt 11.2.1), Einstellungen (Abschnitt 11.2.2), Fehlercodes (Abschnitt 11.2.3) und Stream-Typen (Abschnitt 11.2.4).

Implementierungen MÜSSEN (MUST) unbekannte oder nicht unterstützte Werte in allen erweiterbaren Protokollelementen ignorieren. Implementierungen MÜSSEN (MUST) Daten verwerfen oder das Lesen auf unidirektionalen Streams abbrechen, die unbekannte oder nicht unterstützte Typen haben. Dies bedeutet, dass jeder dieser Erweiterungspunkte sicher von Erweiterungen ohne vorherige Vereinbarung oder Verhandlung verwendet werden kann. Wenn jedoch ein bekannter Frame-Typ an einem bestimmten Ort erforderlich ist, wie z. B. der SETTINGS-Frame als erster Frame des Kontrollstreams (siehe Abschnitt 6.2.1), erfüllt ein unbekannter Frame-Typ diese Anforderung nicht und SOLLTE (SHOULD) als Fehler behandelt werden.

Erweiterungen, die die Semantik bestehender Protokollkomponenten ändern könnten, MÜSSEN (MUST) vor ihrer Verwendung ausgehandelt werden. Beispielsweise kann eine Erweiterung, die das Layout des HEADERS-Frames ändert, nicht verwendet werden, bis der Peer ein positives Signal gegeben hat, dass dies akzeptabel ist. Die Koordinierung, wann ein solches überarbeitetes Layout in Kraft tritt, könnte sich als komplex erweisen. Daher ist es wahrscheinlich effektiver, neue Identifikatoren für neue Definitionen bestehender Protokollelemente zuzuweisen.

Dieses Dokument schreibt keine spezifische Methode zur Aushandlung der Verwendung einer Erweiterung vor, weist jedoch darauf hin, dass eine Einstellung (Abschnitt 7.2.4.1) für diesen Zweck verwendet werden könnte. Wenn beide Peers einen Wert setzen, der die Bereitschaft zur Verwendung der Erweiterung anzeigt, kann die Erweiterung verwendet werden. Wenn eine Einstellung für die Erweiterungsaushandlung verwendet wird, MUSS (MUST) der Standardwert so definiert werden, dass die Erweiterung deaktiviert ist, wenn die Einstellung weggelassen wird.


10. Sicherheitsbetrachtungen​

Die Sicherheitsbetrachtungen für HTTP/3 sollten denen von HTTP/2 mit TLS entsprechen. Viele der Betrachtungen aus Abschnitt 10 von [HTTP/2] gelten jedoch für [QUIC-TRANSPORT] und werden dort behandelt.

10.1. Serverautorität​

HTTP/3 stützt sich auf die Definition von Autorität in HTTP. Sicherheitsbetrachtungen zur Herstellung von Autorität werden in Abschnitt 17.1 von [HTTP] behandelt.

10.2. Protokollübergreifende Angriffe​

Die Verwendung von ALPN im TLS- und QUIC-Handshake legt das beabsichtigte Anwendungsprotokoll fest, bevor Bytes der Anwendungsschicht verarbeitet werden. Dies gibt Endpunkten eine starke Zusicherung, dass der Peer dasselbe Protokoll verwendet.

Dies garantiert keinen Schutz vor allen protokollübergreifenden Angriffen. Abschnitt 21.5 von [QUIC-TRANSPORT] beschreibt einige Möglichkeiten, wie Klartext aus QUIC-Paketen für Anfragenfälschungen gegen Endpunkte ohne authentifizierten Transport verwendet werden kann.

10.3. Angriffe durch Kapselung über Zwischenstellen​

Die Feldkodierung von HTTP/3 erlaubt die Darstellung von Feldnamen, die in der von HTTP verwendeten Syntax ungültig sind, siehe Abschnitt 5.1 von [HTTP]. Anfragen oder Antworten mit ungültigen Feldnamen müssen als fehlerhaft behandelt werden.

Ebenso kann HTTP/3 ungültige Feldwerte übertragen. Die meisten kodierbaren Werte verändern zwar die Feldanalyse nicht, doch Wagenrücklauf (ASCII 0x0d), Zeilenvorschub (ASCII 0x0a) und das Nullzeichen (ASCII 0x00) können von Angreifern ausgenutzt werden, wenn sie wortgetreu weitergegeben werden.

10.4. Zwischenspeicherbarkeit gepushter Antworten​

Für gepushte Antworten gibt es keine explizite Anfrage des Clients; die Anfrage wird vom Server in einem PUSH_PROMISE-Frame bereitgestellt.

Wenn mehrere Mandanten Ressourcen auf demselben Server teilen, muss der Server sicherstellen, dass Mandanten keine Repräsentationen von Ressourcen pushen können, für die sie nicht berechtigt sind.

10.5. Betrachtungen zu Dienstverweigerung​

Der Betrieb einer HTTP/3-Verbindung kann im Vergleich zu einer HTTP/1.1- oder HTTP/2-Verbindung ein größeres Ressourcenengagement erfordern.

Die Fähigkeit, nicht definierte Protokollelemente zu senden, die der Peer ignorieren muss, kann missbraucht werden und beim Peer zusätzlichen Verarbeitungsaufwand verursachen.

Endpunkte, die ein solches Verhalten nicht überwachen, setzen sich dem Risiko von Dienstverweigerungsangriffen aus. Implementierungen SOLLTEN die Nutzung dieser Funktionen nachverfolgen und ihre Nutzung begrenzen.

10.5.1. Begrenzungen der Feldabschnittsgröße​

Große Feldabschnitte (Abschnitt 4.1) können dazu führen, dass eine Implementierung erhebliche Zustandsinformationen vorhalten muss. Ein Endpunkt kann die Einstellung SETTINGS_MAX_FIELD_SECTION_SIZE (Abschnitt 4.2.2) verwenden, um dem Peer Grenzen mitzuteilen, die für die Größe von Feldabschnitten gelten können.

10.5.2. CONNECT-Probleme​

Die Methode CONNECT kann eine unverhältnismäßige Last auf einem Proxy erzeugen, weil das Erzeugen von Streams im Vergleich zum Erzeugen und Aufrechterhalten von TCP-Verbindungen relativ preiswert ist.

10.6. Verwendung von Kompression​

Wenn Kompression vertrauliche Daten im selben Kontext wie von einem Angreifer kontrollierte Daten komprimiert, kann sie einem Angreifer die Wiederherstellung vertraulicher Daten ermöglichen. HTTP/3 aktiviert Feldkompression, siehe Abschnitt 4.2.

Implementierungen, die über einen sicheren Kanal kommunizieren, dürfen Inhalte mit vertraulichen und von Angreifern kontrollierten Daten nicht komprimieren, es sei denn, für jede Datenquelle wird ein separater Kompressionskontext verwendet.

10.7. Padding und Verkehrsanalyse​

Padding kann verwendet werden, um die genaue Größe des Frame-Inhalts zu verschleiern und bestimmte Angriffe innerhalb von HTTP abzumildern.

10.8. Frame-Analyse​

Mehrere Protokollelemente enthalten verschachtelte Längenelemente. Implementierungen müssen sicherstellen, dass die Länge eines Frames genau der Länge der darin enthaltenen Felder entspricht.

10.9. Frühe Daten​

Die Verwendung von 0-RTT mit HTTP/3 birgt das Risiko von Wiederholungsangriffen. Die in [HTTP-REPLAY] beschriebenen Maßnahmen gegen Wiederholungsangriffe müssen bei der Verwendung von HTTP/3 mit 0-RTT angewendet werden.

10.10. Migration​

Einige HTTP-Implementierungen verwenden die Clientadresse für Protokollierung oder Zugriffskontrolle. Da sich die Adresse eines QUIC-Clients während einer Verbindung ändern kann, müssen solche Implementierungen die aktuelle Clientadresse aktiv abrufen oder ausdrücklich akzeptieren, dass sich die ursprüngliche Adresse ändern kann.

10.11. Datenschutzbetrachtungen​

Mehrere Eigenschaften von HTTP/3 ermöglichen Beobachtern, Vorgänge einzelner Clients oder Server im Zeitverlauf miteinander zu verknüpfen. Dazu gehören Werte von Einstellungen, Reaktionszeiten auf Stimuli und die Behandlung von Funktionen, die durch Einstellungen gesteuert werden.

Die Bevorzugung einer einzelnen QUIC-Verbindung durch HTTP/3 ermöglicht es, die Aktivitäten eines Benutzers auf einer Website miteinander zu verknüpfen.


11. IANA-Betrachtungen​

Dieses Dokument registriert eine neue ALPN-Protokoll-ID, Abschnitt 11.1, und erstellt neue Register für die Verwaltung der Zuweisung von Codepoints in HTTP/3.

11.1. Registrierung der HTTP/3-Kennzeichenfolge​

Dieses Dokument erstellt im mit [RFC7301] eingerichteten Register „TLS Application-Layer Protocol Negotiation (ALPN) Protocol IDs“ eine neue Registrierung zur Identifizierung von HTTP/3.

Die Zeichenfolge „h3“ identifiziert HTTP/3:

  • Protokoll: HTTP/3
  • Identifikationssequenz: 0x68 0x33 („h3“)
  • Spezifikation: Dieses Dokument

11.2. Neue Register​

Die in diesem Dokument erstellten neuen Register arbeiten nach den in Abschnitt 22.1 von [QUIC-TRANSPORT] dokumentierten QUIC-Registrierungsrichtlinien. Alle diese Register enthalten den allgemeinen Satz von Feldern aus Abschnitt 22.1.1 von [QUIC-TRANSPORT]. Sie werden unter der Überschrift „Hypertext Transfer Protocol Version 3 (HTTP/3)“ zusammengefasst.

Die anfänglichen Zuweisungen in diesen Registern haben alle den Status „permanent“ und nennen die IETF als Änderungsverantwortliche sowie die HTTP-Arbeitsgruppe ([email protected]) als Kontakt.

11.2.1. Frame-Typen​

Dieses Dokument richtet ein Register für HTTP/3-Frame-Type-Codes ein. Das Register „HTTP/3 Frame Types“ verwaltet einen 62-Bit-Raum.

Tabelle 2: Anfängliche HTTP/3-Frame-Typen

Frame-TypWertSpezifikation
DATA0x00Abschnitt 7.2.1
HEADERS0x01Abschnitt 7.2.2
Reserviert0x02Dieses Dokument
CANCEL_PUSH0x03Abschnitt 7.2.3
SETTINGS0x04Abschnitt 7.2.4
PUSH_PROMISE0x05Abschnitt 7.2.5
Reserviert0x06Dieses Dokument
GOAWAY0x07Abschnitt 7.2.6
MAX_PUSH_ID0x0dAbschnitt 7.2.7

11.2.2. Einstellungsparameter​

Dieses Dokument richtet ein Register für HTTP/3-Einstellungen ein. Das Register „HTTP/3 Settings“ verwaltet einen 62-Bit-Raum.

Tabelle 3: Anfängliche HTTP/3-Einstellungen

EinstellungsnameWertSpezifikationVorgabewert
MAX_FIELD_SECTION_SIZE0x06Abschnitt 4.2.2Unbegrenzt

11.2.3. Fehlercodes​

Dieses Dokument richtet ein Register für HTTP/3-Fehlercodes ein. Das Register „HTTP/3 Error Codes“ verwaltet einen 62-Bit-Raum.

Die von diesem Dokument registrierten Einträge sind in Abschnitt 8.1 aufgeführt.

11.2.4. Stream-Typen​

Dieses Dokument richtet ein Register für unidirektionale HTTP/3-Stream-Typen ein. Das Register „HTTP/3 Stream Types“ verwaltet einen 62-Bit-Raum.

Tabelle 5: Anfängliche HTTP/3-Stream-Typen

Stream-TypWertSpezifikationSender
Steuerungsstream0x00Abschnitt 6.2.1Beide
Push-Stream0x01Abschnitt 4.6Server

Anhang A. Überlegungen zum Übergang von HTTP/2 (Considerations for Transitioning from HTTP/2)​

HTTP/3 basiert auf dem HTTP/2-Design und teilt die Kernsemanktik. Dieser Anhang fasst die Hauptunterschiede zwischen HTTP/2 und HTTP/3 zusammen, um Implementierern zu helfen, die Beziehung zwischen den beiden Protokollen zu verstehen.

A.1. Streams​

HTTP/3 verwendet QUIC-Streams, während HTTP/2 eine Stream-Abstraktion über TCP verwendet. Hauptunterschiede:

  • Stream-Identifikatoren: Stream-IDs in HTTP/3 werden von QUIC zugewiesen, nicht von HTTP/3
  • Stream-Priorität: HTTP/3 enthält nicht das Stream-Prioritätsschema von HTTP/2
  • Flusskontrolle: HTTP/3 verwendet die Flusskontrollmechanismen von QUIC

A.2. HTTP-Frame-Typen (HTTP Frame Types)​

Viele HTTP/2-Frame-Typen werden in HTTP/3 beibehalten oder modifiziert:

Beibehaltene Frame-Typen:

  • DATA (0x00) - Ähnliche Funktionalität
  • HEADERS (0x01) - Ähnliche Funktionalität
  • SETTINGS (0x04) - Ähnlich, aber nur auf Kontrollstream
  • PUSH_PROMISE (0x05) - Ähnliche Funktionalität
  • GOAWAY (0x07) - Ähnliche Funktionalität

Entfernte oder ersetzte HTTP/2-Frame-Typen:

  • PRIORITY (0x02) - In HTTP/3 entfernt
  • RST_STREAM (0x03) - Durch QUICs RESET_STREAM ersetzt
  • PING (0x06) - Durch QUICs PING-Frame ersetzt
  • WINDOW_UPDATE (0x08) - Durch QUICs Flusskontrolle ersetzt
  • CONTINUATION (0x09) - In HTTP/3 nicht erforderlich

Neue Frame-Typen in HTTP/3:

  • CANCEL_PUSH (0x03) - Server-Push abbrechen
  • MAX_PUSH_ID (0x0d) - Push-ID-Raum kontrollieren

A.3. HTTP/2-SETTINGS-Parameter (HTTP/2 SETTINGS Parameters)​

Einstellungen in HTTP/3 unterscheiden sich von HTTP/2:

Entfernte Einstellungen:

  • SETTINGS_HEADER_TABLE_SIZE - Durch QPACK-Einstellungen ersetzt
  • SETTINGS_ENABLE_PUSH - Über MAX_PUSH_ID gesteuert
  • SETTINGS_MAX_CONCURRENT_STREAMS - Durch QUIC-Transportparameter gesteuert
  • SETTINGS_INITIAL_WINDOW_SIZE - Durch QUIC-Flusskontrolle ersetzt
  • SETTINGS_MAX_FRAME_SIZE - In HTTP/3 nicht erforderlich
  • SETTINGS_MAX_HEADER_LIST_SIZE - Durch SETTINGS_MAX_FIELD_SECTION_SIZE ersetzt

Beibehaltene Einstellungen:

  • SETTINGS_MAX_FIELD_SECTION_SIZE (0x06) - Ähnlich wie SETTINGS_MAX_HEADER_LIST_SIZE von HTTP/2

A.4. HTTP/2-Fehlercodes (HTTP/2 Error Codes)​

HTTP/3 definiert einen eigenen Satz von Fehlercodes, die sich von den Fehlercodes von HTTP/2 unterscheiden. Implementierer sollten die Zuordnungsbeziehungen beachten, aber keine direkte Eins-zu-Eins-Entsprechung annehmen.

A.5. Weitere Unterschiede (Other Differences)​

Verbindungsverwaltung:

  • HTTP/3 verwendet QUICs Verbindungsverwaltung, einschließlich Verbindungsmigration und Multipfad-Unterstützung
  • HTTP/2s Verbindungspräambel ist nicht erforderlich

Server-Push:

  • Der Server-Push-Mechanismus in HTTP/3 ähnelt HTTP/2, verwendet jedoch unterschiedliche Frames und Stream-Typen
  • Push-IDs sind in HTTP/3 explizit

Feldkomprimierung:

  • HTTP/3 verwendet QPACK anstelle von HPACK
  • QPACK ist für die Handhabung der ungeordneten Zustellung konzipiert

Erweiterbarkeit:

  • HTTP/3 bietet flexiblere Erweiterungsmechanismen
  • Neue Frame-Typen, Einstellungen und Stream-Typen können ohne Verhandlung verwendet werden