TsgcHTTP3Server implementiert einen HTTP/3-Server (RFC 9114), der HTTP-Anfragen über QUIC bedient.
TsgcHTTP3Server implementiert einen HTTP/3-Server gemäß RFC 9114. HTTP/3 überträgt HTTP-Anfragen und -Antworten über QUIC, einen UDP-basierten Transport mit eingebautem TLS 1.3, sodass jede Verbindung verschlüsselt und ohne Head-of-Line-Blocking gemultiplext ist: Ein verlorenes Paket blockiert nur den Anfrage-Stream, zu dem es gehörte, nicht die gesamte Verbindung. Standardmäßig läuft der Server auf dem nativen QUIC-Listener, den OpenSSL 3.5 oder neuer bereitstellt, und fällt auf die sgc-QUIC-Engine zurück, wenn dieser Listener nicht verfügbar ist (siehe QUICMode), daher ist keine externe HTTP/3-Bibliothek erforderlich.
Die Komponente besitzt den gesamten HTTP/3-Stack oberhalb von QUIC: Sie öffnet die Control- und QPACK-Streams, tauscht SETTINGS aus, decodiert QPACK-Header-Abschnitte, setzt die Anfrage-Frames auf jedem Stream wieder zusammen und löst ein Ereignis pro vollständiger Anfrage aus. Anfragen werden gemultiplext, sodass mehrere auf einer einzigen Verbindung gleichzeitig unterwegs sein können, jede auf ihrem eigenen QUIC-Stream.
TLS ist zwingend erforderlich. QUIC besitzt keinen Klartextmodus, daher kann der Server ohne Zertifikat und passenden privaten Schlüssel nicht starten. Clients prüfen dieses Zertifikat genau so, wie sie ein HTTPS-Zertifikat prüfen würden, das heißt, ein selbstsigniertes Zertifikat funktioniert nur mit Clients, die so konfiguriert sind, dass sie ihm vertrauen. HTTP/3 läuft außerdem über UDP statt über TCP, daher muss der lauschende Port in jeder dazwischenliegenden Firewall für UDP geöffnet sein.
Folgen Sie den nachstehenden Schritten, um diese Komponente zu konfigurieren:
1. Erstellen Sie eine neue Instanz von TsgcHTTP3Server und legen Sie den Port fest, auf dem der Server lauschen wird. HTTP/3 verwendet UDP, und der geerbte Standardport ist für HTTP/3 nicht sinnvoll, setzen Sie ihn also immer. Port 443 ist in der Produktion die übliche Wahl, da sich damit dieselbe Autorität über den Alt-Svc-Header einer HTTPS-Site ankündigen lässt.
2. Legen Sie das Zertifikat und den privaten Schlüssel in QUICOptions.SSLOptions fest. Beide sind PEM-Dateien und beide sind erforderlich, weil QUIC immer TLS 1.3 aushandelt.
3. Behandeln Sie das Ereignis OnH3Request und rufen Sie Start auf. Der Parameter aResponse wird vom Server mit einem auf 200 voreingestellten StatusCode erstellt; setzen Sie dessen StatusCode, ContentType und Data, und der Server kodiert ihn per QPACK und sendet ihn automatisch, sobald der Handler zurückkehrt. Ein Aufruf von SendResponse ist nicht erforderlich. Beispiel:
oServer := TsgcHTTP3Server.Create(nil);
oServer.Port := 443;
oServer.QUICOptions.SSLOptions.CertFile := 'cert.pem';
oServer.QUICOptions.SSLOptions.KeyFile := 'key.pem';
oServer.OnH3Request := OnH3RequestEvent;
oServer.Start;
procedure OnH3RequestEvent(Sender: TObject; const aConnection:
TsgcQUICServerConnection; const aRequest: TsgcHTTP3Request;
const aResponse: TsgcHTTP3Response);
begin
aResponse.StatusCode := 200;
aResponse.ContentType := 'text/plain; charset=utf-8';
aResponse.Data := TEncoding.UTF8.GetBytes('Hello HTTP/3');
end;
Eine Anfrage wird beantwortet, indem Sie das TsgcHTTP3Response füllen, das der Server an OnH3Request übergibt. Das Objekt gehört dem Server, füllen Sie es also und geben Sie es nicht frei.
| Member | Typ | Beschreibung |
|---|---|---|
StatusCode | Integer | Wird als Pseudo-Header :status gesendet. Voreingestellt auf 200. |
ContentType | string | Wird als content-type-Header gesendet, wenn er nicht leer ist. |
Data | TBytes | Der Antwort-Body. Kodieren Sie Zeichenfolgen explizit, normalerweise mit TEncoding.UTF8.GetBytes. |
Headers | TStringList | Zusätzliche Antwort-Header, ein Eintrag pro Header in der Form name=value. |
ContentLength | Int64 | Wird beim Senden nicht verwendet: content-length wird aus der Länge von Data berechnet. |
Der Server schreibt :status und fügt content-type und content-length für Sie hinzu, diese müssen also nie von Hand hinzugefügt werden. Benutzerdefinierte Header verwenden name=value und nicht name: value. Pseudo-Header und die von RFC 9114 verbotenen verbindungsspezifischen Header (connection, keep-alive, proxy-connection, transfer-encoding und upgrade) werden verworfen statt gesendet. Eine Antwort auf eine HEAD-Anfrage wird nur als Header-Abschnitt gesendet, der Body wird automatisch unterdrückt. Siehe OnH3Request für die vollständige Anfrage- und Antwortreferenz.
Server Push. Rufen Sie PushPromise innerhalb von OnH3Request auf, um eine zugehörige Ressource zuzusagen und sie auf einem servergestarteten Push-Stream zu liefern. Die Methode gibt False zurück, wenn der Client über MAX_PUSH_ID kein Push-Budget gewährt hat, was normal ist und geprüft werden muss. Aktuelle verbreitete Browser implementieren HTTP/3-Server-Push nicht, es ist daher vor allem mit Clients nützlich, die Sie selbst kontrollieren.
Extended CONNECT und Tunnel. Wird eine CONNECT-Anfrage mit einem 2xx-Status beantwortet, wird ihr Anfrage-Stream zu einem Tunnel: Der Stream bleibt offen, nachfolgende DATA-Frames sind kein Anfrage-Body mehr und treffen bei OnH3TunnelData ein, und TunnelSend schreibt Bytes zurück. Setzen Sie Settings.EnableConnectProtocol, um Extended CONNECT (RFC 9220) anzukündigen, womit ein Client ein CONNECT mit einem :protocol-Pseudo-Header senden kann. Wird H3Settings.Settings.WebTransportMaxSessions über null gesetzt, aktiviert dies zusätzlich WebTransport und löst OnWebTransportSession für jede Sitzung aus, die angenommen wird, sofern der Handler sie nicht ablehnt.
Kontrolliertes Herunterfahren. Stop schließt Verbindungen sofort. Um sie stattdessen auslaufen zu lassen, senden Sie zuerst auf jeder Verbindung SendGoAway: Es teilt dem Peer den letzten Anfrage-Stream mit, den der Server bearbeiten wird, sodass Clients keine neuen Streams mehr öffnen und den Rest anderswo wiederholen können, während laufende Anfragen abgeschlossen werden. Rufen Sie Stop auf, sobald sie das getan haben.
| Name | Beschreibung |
|---|---|
| Port | UDP-Port, auf dem der HTTP/3-Server lauscht. |
| QUICOptions | QUIC-Transportoptionen, einschließlich des obligatorischen Zertifikats und privaten Schlüssels sowie der Verbindungsbeschränkungen. |
| H3Settings | HTTP/3-Protokolleinstellungen, die Peers angekündigt werden: QPACK- und Field-Section-Limits, Extended CONNECT und WebTransport. |
| Active | Startet oder stoppt den HTTP/3-Server-Listener. |
| Name | Beschreibung |
|---|---|
| Start | Startet den QUIC-Listener und beginnt, HTTP/3-Verbindungen anzunehmen. |
| Stop | Stoppt den Listener und schließt alle aktiven Verbindungen. |
| SendGoAway | Sendet einen GOAWAY-Frame, um eine ordnungsgemäße Beendigung der Verbindung einzuleiten. |
| PushPromise | Pusht eine zugehörige Ressource aus OnH3Request heraus an den Client. |
| Name | Beschreibung |
|---|---|
| OnH3Request | Wird ausgelöst, wenn eine vollständige HTTP/3-Anfrage empfangen wird, sodass die Anwendung die Antwort füllen kann. |
| OnH3Connect | Wird ausgelöst, wenn ein Client eine HTTP/3-Verbindung aufbaut. |
| OnH3Disconnect | Wird ausgelöst, wenn eine HTTP/3-Verbindung geschlossen wird. |
| OnH3Exception | Wird ausgelöst, wenn während der Bedienung einer HTTP/3-Verbindung eine Ausnahme ausgelöst wird. |
Das folgende Beispiel startet einen HTTP/3-Server, der einige Pfade routet und einen JSON- oder Klartext-Body zurückgibt, Verbindungen protokolliert und den Server sauber stoppt. Die Antwort wird in OnH3Request gefüllt und vom Server automatisch gesendet.
// start
oServer := TsgcHTTP3Server.Create(nil);
oServer.Port := 4433;
oServer.QUICOptions.SSLOptions.CertFile := 'server.crt';
oServer.QUICOptions.SSLOptions.KeyFile := 'server.key';
oServer.OnH3Request := OnH3RequestEvent;
oServer.OnH3Connect := OnH3ConnectEvent;
oServer.OnH3Disconnect := OnH3DisconnectEvent;
oServer.OnH3Exception := OnH3ExceptionEvent;
oServer.Start;
procedure OnH3ConnectEvent(Sender: TObject; const aConnection:
TsgcQUICServerConnection);
begin
Log('HTTP/3 client connected: ' + aConnection.PeerIP + ':' +
IntToStr(aConnection.PeerPort));
end;
procedure OnH3DisconnectEvent(Sender: TObject; const aConnection:
TsgcQUICServerConnection; aCode: Int64; const aReason: string);
begin
Log('HTTP/3 client disconnected: ' + aReason);
end;
procedure OnH3ExceptionEvent(Sender: TObject; const aConnection:
TsgcQUICServerConnection; const aException: Exception);
begin
Log('HTTP/3 error: ' + aException.Message);
end;
// answer a request
procedure OnH3RequestEvent(Sender: TObject; const aConnection:
TsgcQUICServerConnection; const aRequest: TsgcHTTP3Request;
const aResponse: TsgcHTTP3Response);
begin
if aRequest.Path = '/api/time' then
begin
aResponse.StatusCode := 200;
aResponse.ContentType := 'application/json';
aResponse.Data := TEncoding.UTF8.GetBytes(
'{"time":"' + DateTimeToStr(Now) + '"}');
end
else
begin
aResponse.StatusCode := 404;
aResponse.ContentType := 'text/plain; charset=utf-8';
aResponse.Data := TEncoding.UTF8.GetBytes('Not Found');
end;
end;
// stop
oServer.Stop;
oServer.Free;
| Voraussetzung | Detail |
|---|---|
| Edition | All-Access-Edition. |
| Compiler-Define | HTTP/3 wird deaktiviert ausgeliefert. Entfernen Sie die Kommentarzeichen von {$DEFINE SGC_PACK_HTTP3} in sgcVer.inc, wodurch SGC_QUIC, SGC_HTTP3 und SGC_WEBTRANSPORT aktiviert werden. |
| Indy | SGC_INDY_LIB muss aktiviert sein: Die HTTP/3-Defines sind darin verschachtelt. |
| Unit | sgcHTTP3_Server oder sgcHTTP für die registrierte Komponente TsgcHTTP3Server. |
| OpenSSL | OpenSSL 3.5 oder neuer mit QUICOptions.SSLOptions.IOHandler = iohOpenSSL. Auf einem älteren OpenSSL gibt es keinen Fallback. Mit iohNativeTLS wird kein OpenSSL benötigt. |
| Transport | UDP. Der Lauschport muss für UDP geöffnet sein, nicht für TCP. |
| .NET | Der .NET-Server nimmt QUIC-Verbindungen an (.NET 8.0 oder höher, MsQuic) und implementiert die HTTP/3-Framing- und QPACK-Schicht, die er für den SETTINGS-Handshake und für Extended CONNECT / WebTransport verwendet. Er bedient weiterhin keine einfachen HTTP/3-Anfragen: Sie werden nie an OnH3Request weitergeleitet, und SendResponse, SendGoAway und SendPush sind nicht mit der Framing-Schicht verbunden, sie tun also nichts. Verwenden Sie Delphi/C++Builder, um HTTP/3-Anfragen zu bedienen. |