HTTP/3

HTTP/3 ist die dritte Hauptversion von HTTP, definiert in RFC 9114. Sie lässt die HTTP-Semantik unverändert und ersetzt den Transport durch QUIC.

Einführung

HTTP/3 behält alles bei, was Sie bereits über HTTP wissen: dieselben Methoden, dieselben Statuscodes, dieselben Headerfelder, dieselben Caching- und Authentifizierungsregeln. Was sich ändert, ist der Träger. HTTP/1.1 und HTTP/2 laufen über TCP mit darüberliegendem TLS. HTTP/3 läuft über QUIC, einen UDP-basierten Transport mit eingebautem TLS 1.3.

Da die HTTP-Semantik unverändert bleibt, verhält sich eine von HTTP/1.1 oder HTTP/2 nach HTTP/3 portierte Anwendung genauso. Sie setzen ein GET ab, Sie erhalten einen Statuscode und einen Body zurück.

RFCTitleWas es definiert
RFC 9114HTTP/3Die Abbildung von HTTP auf QUIC: Frames, Anfrage- und Antwort-Streams, unidirektionale Stream-Typen, Einstellungen, Server-Push und die HTTP/3-Fehlercodes.
RFC 9204QPACK: Field Compression for HTTP/3Header-Komprimierung, die für QUIC entwickelt wurde und eine statische Tabelle sowie eine dynamische Tabelle verwendet, die auf dedizierten Encoder- und Decoder-Streams übertragen wird.
RFC 9000QUIC-TransportDer Transport, auf dem HTTP/3 übertragen wird. Siehe QUIC.

Warum nicht HPACK

HTTP/2 komprimiert Header mit HPACK, das voraussetzt, dass Header in der Reihenfolge eintreffen, in der sie gesendet wurden, eine Annahme, die TCP garantiert. QUIC-Streams können in abweichender Reihenfolge zugestellt werden, daher würde HPACK Head-of-Line-Blocking auf der Komprimierungsschicht wieder einführen. QPACK löst dies, indem es Aktualisierungen der dynamischen Tabelle auf separaten unidirektionalen Streams überträgt und indem eine Anfrage nur so lange blockiert, bis die Tabelleneinträge eingetroffen sind, von denen sie tatsächlich abhängt.

HTTP/3 im Vergleich zu HTTP/1.1 und HTTP/2

 HTTP/1.1HTTP/2HTTP/3
SpezifikationRFC 9112RFC 9113RFC 9114
TransportTCPTCPQUIC über UDP
VerschlüsselungOptional, TLS darüber gelagertIn der Spezifikation optional, in der Praxis TLSImmer aktiv, TLS 1.3 ist Teil des Transports
MultiplexingKeine. Eine Anfrage gleichzeitig pro Verbindung, daher öffnen Clients mehrere VerbindungenViele Streams über eine TCP-VerbindungViele Streams, vom Transport selbst bereitgestellt
Head-of-Line-BlockingJa, auf AnfrageebeneAuf Anwendungsebene beseitigt, ein verlorenes TCP-Segment blockiert jedoch weiterhin jeden StreamEntfällt. Ein verlorenes Paket blockiert nur die Streams, deren Daten es transportiert hat
Header-KomprimierungKeine, Header sind KlartextHPACK (RFC 7541)QPACK (RFC 9204)
NachrichtenformatTextBinäre FramesBinäre Frames über QUIC-Streams
Handshake-KostenTCP-Handshake, dann ein separater TLS-HandshakeTCP-Handshake, dann ein separater TLS-HandshakeTransport und TLS in einem Flight kombiniert, mit 0-RTT bei einer wiederaufgenommenen Sitzung
VerbindungsmigrationNein, die Verbindung ist an das Vier-Tupel gebundenNoJa, die Verbindung wird durch eine Connection-ID identifiziert
Server-PushNoJa, in der Praxis veraltetJa, gesteuert über Push-IDs und ein clientgesteuertes Limit

Unterstützte HTTP-Methoden

Der Client unterstützt die zehn Methoden, die in der Aufzählung Th3Methods (sgcHTTP3_Types.pas) deklariert sind. Jede besitzt eine blockierende Methode, und die meisten haben zusätzlich eine asynchrone Variante. Diese Tabelle dient der Orientierung, siehe TsgcHTTP3Client für die vollständigen Signaturen, Überladungen und Standardwerte der Parameter.

MethodeAufzählungswertClient-MethodeAsync-Variante
GETh3meGetGetGetAsync
HEADh3meHeadHead—
POSTh3mePostPostPostAsync
PUTh3mePutPutPutAsync
DELETEh3meDeleteDeleteDeleteAsync
PATCHh3mePatchPatchPatchAsync
OPTIONSh3meOptionsRequestOptionsOptionsAsync
TRACEh3meTraceTraceTraceAsync
CONNECTh3meConnectConnectConnectAsync
QUERYh3meQueryQueryQueryAsync

Hinweise zu zweien davon:

Erkennung mit Alt-Svc

Ein Client kann nicht davon ausgehen, dass ein Server HTTP/3 spricht, und es gibt keinen HTTP/3-Upgrade-Handshake, der dem von HTTP/2 entspricht. Der übliche Weg zur Erkennung ist der Antwort-Header Alt-Svc (RFC 7838): ein über HTTP/1.1 oder HTTP/2 erreichter Server kündigt an, dass derselbe Origin auch über HTTP/3 unter einem bestimmten Host und Port verfügbar ist, und der Client merkt sich das für künftige Anfragen. Der Client parst diesen Header und stellt ihn über das Ereignis OnAltSvc bereit, sodass Ihre Anwendung entscheiden kann, wann umgeschaltet wird.

Server-Push

Ein Server kann eine Antwort pushen, die der Client nicht angefordert hat, sodass ein Client, der eine Seite abruft, keinen zweiten Roundtrip für eine Ressource benötigt, von der der Server weiß, dass sie gebraucht wird. Jeder Push trägt eine Push-ID. Der Client behält die Kontrolle: Er kündigt mit SetMaxPushId an, wie viele Pushes er akzeptiert, wird über OnPushPromise über einen eingehenden Push benachrichtigt und kann einen Push mit CancelPush ablehnen.

Extended CONNECT

Extended CONNECT (RFC 9220 für HTTP/3, das den von RFC 8441 für HTTP/2 definierten Mechanismus übernimmt) verwandelt einen Anfrage-Stream in einen Tunnel für ein anderes Protokoll. Es fügt der Methode CONNECT einen :protocol-Pseudo-Header hinzu, damit der Endpunkt weiß, welches Protokoll er tunneln soll.

Es ist nur verfügbar, wenn der Server SETTINGS_ENABLE_CONNECT_PROTOCOL in seinen Einstellungen ankündigt. Der Client stellt ExtendedConnect bereit, das False zurückgibt, wenn der Server es nie angekündigt hat oder wenn der Antwortstatus kein 2xx ist. Sobald der Tunnel offen ist, schreiben Sie mit TunnelSend darauf und empfangen über OnTunnelData.

WebTransport

WebTransport baut auf Extended CONNECT auf. Es handelt eine Sitzung über einen Extended-CONNECT-Stream aus und gibt der Anwendung dann direkt QUIC-Streams, was für latenzarmen, bidirektionalen Verkehr außerhalb des Anfrage/Antwort-Schemas genau das Richtige ist. Die Spezifikation bietet auch Datagramme, sie können jedoch auf der QUIC-Engine, die diese Bibliothek mitliefert, nicht übertragen werden, daher ist WebTransport hier auf Streams beschränkt. Es benötigt vom Server sowohl SETTINGS_ENABLE_CONNECT_PROTOCOL als auch ein SETTINGS_WEBTRANSPORT_MAX_SESSIONS ungleich null, was der Client über ServerSupportsWebTransport prüft. Da eine Sitzung mehrere Streams auf einer QUIC-Verbindung benötigt, erfordert WebTransport die integrierte OpenSSL-QUIC-Engine, siehe QUIC. Einzelheiten finden Sie auf der Seite WebTransport.

Komponenten

KomponenteBeschreibung
TsgcHTTP3ClientSendet HTTP-Anfragen über HTTP/3, mit blockierenden und asynchronen Methoden, Alt-Svc-Erkennung, Server Push, Extended-CONNECT-Tunneln und WebTransport.
TsgcHTTP3ServerNimmt HTTP/3-Verbindungen an und bedient Anfragen über QUIC. Er leitet sich von TsgcQUICServer ab und ergänzt HTTP/3-Framing, Einstellungen und Anfrageverteilung.
WebTransportSitzungen und Streams über HTTP/3, ausgehandelt mit Extended CONNECT. Datagramme werden von der ausgelieferten QUIC-Engine nicht übertragen.

Schnellstart

Verbinden Sie sich mit einem Host und Port und senden Sie dann Anfragen. Der Standardport ist 443.

oClient := TsgcHTTP3Client.Create(nil);
oClient.OnResponse := OnResponseHandler;
oClient.OnAltSvc := OnAltSvcHandler;
oClient.Connect('www.example.com', 443);
vBody := oClient.Get('https://www.example.com/');
oClient.Disconnect;

Der Server bindet einen UDP-Port, lädt ein Zertifikat und einen Schlüssel und löst für jede Anfrage ein Ereignis aus.

oServer := TsgcHTTP3Server.Create(nil);
oServer.Port := 443;
oServer.QUICOptions.SSLOptions.CertFile := 'cert.pem';
oServer.QUICOptions.SSLOptions.KeyFile := 'key.pem';
oServer.OnH3Request := OnH3RequestHandler;
oServer.Start;

HTTP/3 läuft über UDP, daher muss Port 443 über UDP und nicht nur über TCP erreichbar sein. Dies ist der häufigste Grund, warum eine funktionierende HTTP/2-Installation kein HTTP/3 ausliefert.

Der Server bindet die Adresse in Host. Ein Wert, der einen Doppelpunkt enthält, ist ein IPv6-Literal, und jeder andere Wert, ein IPv4-Literal oder ein Hostname, wird über beide Adressfamilien aufgelöst. Ein leeres Host bindet den Dual-Stack-Platzhalter, sodass ein einziger Listener IPv4- und IPv6-Gegenstellen auf demselben Port bedient. Der Client ist URL-gesteuert, daher gehört ein IPv6-Literal dort in eckige Klammern, zum Beispiel oClient.Get('https://[::1]:443/').

Anforderungen

VoraussetzungDetail
EditionAll-Access. Das Pack SGC_PACK_HTTP3 liegt im Block SGC_EDT_ALL von sgcVer.inc.
Pack-DefineSGC_PACK_HTTP3. Es wird in sgcVer.inc auskommentiert ausgeliefert und muss daher ausdrücklich aktiviert werden, bevor HTTP/3 einkompiliert wird.
Feature-DefinesWenn sowohl SGC_PACK_HTTP3 als auch SGC_INDY_LIB aktiviert sind, definiert sgcVer.inc die Symbole SGC_QUIC, SGC_HTTP3 und SGC_WEBTRANSPORT. Die HTTP/3-Komponenten werden unter SGC_HTTP3 kompiliert und die WebTransport-Member unter SGC_WEBTRANSPORT.
IndySGC_INDY_LIB ist erforderlich. Die HTTP/3-Defines sind in einen SGC_INDY_LIB-Guard eingebettet.
OpenSSLOpenSSL 3.5 oder neuer, das standardmäßig die native QUIC-Unterstützung bereitstellt, auf der die Komponenten aufbauen. WebTransport erfordert zusätzlich die integrierte OpenSSL-QUIC-Engine. Mit dem TLS-IOHandler auf iohNativeTLS läuft HTTP/3 ohne OpenSSL auf der sgc-QUIC-Engine, siehe SSL ohne OpenSSL.
UnitssgcHTTP.pas deklariert die Komponenten. HTTP/3 selbst befindet sich in den sgcHTTP3_*-Units, WebTransport in sgcWebTransport.pas und der Transport in den sgcQUIC_*-Units.

Um HTTP/3 zu aktivieren, bearbeiten Sie sgcVer.inc und heben Sie die Auskommentierung des Pack-Defines innerhalb des All-Access-Blocks auf:

{$IFDEF SGC_EDT_ALL} { ALL-ACCESS }
  {$DEFINE SGC_PACK_HTML}
  {$DEFINE SGC_PACK_HTTP3}
  {.$DEFINE SGC_PACK_WEBRTC}
{$ENDIF}

Siehe auch