sgcQUIC in vijf minuten

QUIC en HTTP/3 in native Object Pascal, op de QUIC-engine in OpenSSL. Er worden vier componenten meegeleverd. De kortste weg naar iets werkends is de HTTP/3-client. Daarom doet deze pagina één verzoek, leest de statuscode en is ze precies over welke OpenSSL je nodig hebt.

QUIC RFC 9000 en HTTP/3 RFC 9114
OpenSSL 3.2 en hoger voor de client
All-Access edition

Wat het eerste verzoek nodig heeft

Eén component, één URL en twee OpenSSL-bibliotheken naast je uitvoerbare bestand.

Component

TsgcHTTP3Client op de palettabpagina SGC QUIC, gedeclareerd in sgcQUIC.pas. De pagina bevat ook TsgcQUICClient, TsgcQUICServer en TsgcHTTP3Server.

Unit

sgcQUIC voor het component. Voeg sgcHTTP3_Classes toe voor TsgcHTTP3Response en sgcHTTP_AltSvc als je de Alt-Svc-gebeurtenis afhandelt.

De aanroep

Get(aURL) geeft de body terug als string en veroorzaakt een exception bij een fout. De statuscode en headers komen apart binnen, via OnResponse.

De OpenSSL-vereiste

De client heeft de QUIC-API nodig in OpenSSL 3.2 of hoger, of een quictls-build. De server heeft 3.5 of hoger nodig, omdat die een API aanroept die alleen daar bestaat. Lever libcrypto-3.dll en libssl-3.dll mee naast je uitvoerbare bestand, zoals elke demomap doet.

Vereisten en edities

De editiekolom noemt de define die de code afschermt, met het regelnummer in Source/sgcVer.inc.

Onderdeel Waarde
IDE Delphi 7 tot en met RAD Studio 13 en C++Builder 2007 tot en met 13. Er is geen aparte sgcQUIC-download: de componenten zitten in de sgcWebSockets-packagegroep.
Uses-clausule sgcQUIC, plus sgcHTTP3_Classes voor het responsobject en sgcHTTP_AltSvc voor de Alt-Svc-types.
Packdefine SGC_PACK_QUIC wordt gedefinieerd op regel 872, binnen het {$IFDEF SGC_EDT_ALL}-blok dat loopt van regel 870 tot regel 874. Dus All-Access.
Functiedefines Binnen het {$IFDEF SGC_PACK_QUIC}-blok op regel 894 tot 899: SGC_QUIC op regel 896, SGC_HTTP3 op regel 897 en SGC_WEBTRANSPORT op regel 898. Alle drie staan binnen een {$IFDEF SGC_INDY_LIB} op regel 895, dus een build zonder de aangepaste Indy-bibliotheek krijgt er geen enkele.
OpenSSL, client 3.2 of hoger, of een quictls-build. De bibliotheek zegt dat zelf: de foutmelding wanneer QUIC niet beschikbaar is luidt QUIC is not available. Requires quictls/openssl or OpenSSL 3.2+.
OpenSSL, server 3.5 of hoger. De QUIC-server roept SSL_new_listener aan en de foutmelding wanneer die ontbreekt luidt QUIC Server requires OpenSSL 3.5 or later. msquic wordt niet gebruikt en is niet nodig.
Platforms Geen platformbeveiliging op unitniveau in sgcQUIC.pas, sgcQUIC_Client.pas, sgcHTTP3_Client.pas of sgcHTTP3_Server.pas en alle vier de componenten zijn geregistreerd met ComponentPlatforms(0). De serverunit kiest per platform de socket-API, met zowel een Windows- als een POSIX-tak.

Weet je niet zeker of de engine tijdens runtime aanwezig is? Roep IsOpenSSL_QUIC_Available aan, die teruggeeft of de geladen OpenSSL de QUIC-clientmethode beschikbaar stelt. De meegeleverde QUIC-clientdemo logt dit bij het opstarten, juist hierom.

Installeer en vind de palettabpagina

Er is geen apart sgcQUIC-installatieprogramma. De componenten komen mee met sgcWebSockets en verschijnen zodra de editie ze inschakelt.

1. Uitpakken

Pak de sgcWebSockets-download uit in een map, hieronder {$DIR} genoemd.

2. Bibliotheekpad

Tools, Options, Library. Voeg {$DIR}\source toe en de libmap voor jouw IDE, bijvoorbeeld {$DIR}\libD13\$(Platform).

3. De packages bouwen

Open de packagegroep voor jouw IDE-versie onder {$DIR}\Packages\. Compileer eerst de runtime-.dpk en installeer daarna die van designtime (dcl). Er is geen QUIC-specifiek package.

4. Het palet controleren

Er verschijnt een pagina met de naam SGC QUIC met TsgcQUICClient, TsgcQUICServer, TsgcHTTP3Client en TsgcHTTP3Server. Als de pagina ontbreekt, is de build niet All-Access, want SGC_PACK_QUIC wordt alleen gedefinieerd op regel 872 binnen dat blok.

5. Zet OpenSSL naast de exe

Kopieer libcrypto-3.dll en libssl-3.dll naast je uitvoerbare bestand, 3.2 of hoger voor een client en 3.5 of hoger voor een server. Elke map onder Demos\22.QUIC_Protocol bevat ze, dus je kunt ze daarvandaan kopiëren.

Eén HTTP/3-verzoek

Maak de client aan, koppel drie gebeurtenissen en roep Get aan. Het antwoord komt terug als string en de statuscode komt binnen op OnResponse.

FHTTP3Client.pas
uses
  Classes, SysUtils,
  // sgc
  sgcQUIC, sgcHTTP3_Classes;

procedure TfrmHTTP3Client.FormCreate(Sender: TObject);
begin
  FClient := TsgcHTTP3Client.Create(nil);
  FClient.OnConnect := OnH3Connect;
  FClient.OnError := OnH3Error;
  FClient.OnResponse := OnH3Response;
  FClient.TLSOptions.VerifyCertificate := True;
  FClient.ConnectTimeout := 10000;
  FClient.ReadTimeout := 30000;
  FClient.UserAgent := 'sgcWebSockets/HTTP3Client';
end;

procedure TfrmHTTP3Client.btnGetClick(Sender: TObject);
var
  vResult: string;
begin
  try
    // the target comes from the URL, because Host and Port
    // are read-only on this component
    vResult := FClient.Get('https://www.google.com/');
    memoBody.Lines.Text := vResult;
    DoLog('Response received: ' + IntToStr(Length(vResult)) + ' bytes');
  except
    on E: Exception do
      DoLog('Error: ' + E.Message);
  end;
end;

Post, Put en Delete hebben dezelfde vorm en elk heeft een stream-overload voor een body die je niet in een string wilt bewaren. Connect(const aHost: string; aPort: Integer = 443) opent de verbinding vóór het eerste verzoek als je die twee wilt scheiden.

FHTTP3Client.pas
// OnConnect and OnDisconnect are plain TNotifyEvent on this
// component: one parameter, no connection object.
procedure TfrmHTTP3Client.OnH3Connect(Sender: TObject);
begin
  DoLog('Connected to ' + FClient.Host + ':' + IntToStr(FClient.Port));
end;

procedure TfrmHTTP3Client.OnH3Error(Sender: TObject; const aError: string);
begin
  DoLog('Error: ' + aError);
end;

procedure TfrmHTTP3Client.OnH3Response(Sender: TObject;
  const aResponse: TsgcHTTP3Response);
begin
  DoLog('Status: ' + IntToStr(aResponse.StatusCode));
  memoHeaders.Lines.Assign(aResponse.Headers);
end;

Het lezen van FClient.Host en FClient.Port binnen OnConnect is precies waarvoor die twee eigenschappen dienen. Ze rapporteren de verbinding, ze configureren die niet.

FQUICClient.pas
uses
  Classes, SysUtils,
  // sgc
  sgcIdSSLOpenSSLHeaders;

procedure TfrmQUICClient.FormCreate(Sender: TObject);
begin
  DoLog('OpenSSL QUIC Support:');
  DoLog('  quictls API: ' +
    BoolToStr(IsOpenSSL_QUIC_TLS_Available, True));
  DoLog('  Builtin QUIC (3.2+): ' +
    BoolToStr(IsOpenSSL_QUIC_Available, True));
end;

Voer dit eerst eenmalig uit, voor al het andere. Als beide false melden, heeft de OpenSSL naast je uitvoerbare bestand geen QUIC en is elke verbindingsfout daarna een gevolg van dit ene feit en niet van het netwerk.

De eerste twee tabbladen komen uit de meegeleverde demo Demos\22.QUIC_Protocol\03.HTTP3_Client\FHTTP3Client.pas, met de formulierbesturingselementen vervangen door literals. Het derde is de runtime-beschikbaarheidscontrole uit 01.QUIC_Client\FQUICClient.pas. In die map staan zes QUIC-demo's, waaronder een WebTransport-paar.

Lees de statuscode, niet alleen de body

Get geeft de body terug. Het responsobject bevat al het andere en komt binnen via een eigen gebeurtenis.

De retourwaarde

Get geeft de responsbody terug als string en veroorzaakt een exception bij een fout, dus de demo plaatst het in een try except. Een body van de verwachte lengte is het eerste bewijs.

OnResponse

procedure(Sender: TObject; const aResponse: TsgcHTTP3Response). StatusCode is het getal dat je echt wilt, Headers is een TStringList en GetDataAsString geeft je de body opnieuw vanuit het responsobject.

OnConnect

Een gewone TNotifyEvent. Dat de gebeurtenis wordt aangeroepen, betekent dat QUIC is onderhandeld en de HTTP/3-sessie is geopend. Dat is het onderdeel dat bij een eerste run het vaakst mislukt.

Voordat je de code de schuld geeft

IsOpenSSL_QUIC_Available beantwoordt de enige vraag die het waard is om eerst te stellen. QUIC draait ook over UDP 443 en een netwerk dat TCP 443 toestaat, staat dat niet per se toe.

Wat er de eerste keer meestal misgaat

Zes problemen verklaren bijna elk mislukt eerste verzoek.

Kan niet toewijzen aan Host of Port

Ze zijn alleen-lezen op TsgcHTTP3Client, gedeclareerd als property Host: string read FHost en property Port: Integer read FPort. Ze rapporteren waarmee de client is verbonden. Om een doel te kiezen, geef je een volledige URL mee aan Get of roep je Connect(aHost, aPort) aan.

QUIC is niet beschikbaar

De OpenSSL die je hebt geladen is te oud of is zonder QUIC gebouwd. De client heeft 3.2 of hoger nodig, of quictls. Controleer tijdens runtime met IsOpenSSL_QUIC_Available voordat je het netwerk de schuld geeft.

De server start niet

De QUIC-server heeft OpenSSL 3.5 of hoger nodig, omdat die SSL_new_listener aanroept. Een 3.2-build is genoeg voor de client en niet voor de server en de foutmelding zegt dat uitdrukkelijk.

Verkeerd aantal parameters bij OnConnect

OnConnect en OnDisconnect op dit component zijn gewone TNotifyEvent, dus de handler neemt alleen Sender: TObject. Ze geven je geen verbindingsobject, anders dan de WebSocket-componenten.

UDP is geblokkeerd

QUIC draait over UDP op poort 443 en veel bedrijfsnetwerken staan TCP 443 toe en blokkeren UDP 443. Als een browser de host via HTTP/3 kan bereiken en jouw toepassing niet, verdenk dan de firewall voordat je de code verdenkt.

De palettabpagina ontbreekt

SGC_PACK_QUIC wordt alleen gedefinieerd op regel 872, binnen het All-Access-blok. Het vereist ook SGC_INDY_LIB, omdat het hele packblok op regel 894 tot 899 binnen die beveiliging staat.

Voorbij het eerste verzoek

Vier richtingen, allemaal binnen hetzelfde package.

Draai een HTTP/3-server

TsgcHTTP3Server serveert HTTP/3 rechtstreeks over QUIC. Onthoud de ondergrens van OpenSSL 3.5 aan de serverkant.

HTTP/3-servercomponent

Pure QUIC, zonder HTTP

TsgcQUICClient and TsgcQUICServer geven je QUIC-streams zonder de HTTP/3-laag. Dat is wat je wilt voor een eigen protocol dat multiplexing nodig heeft zonder head-of-line blocking.

QUIC-client en QUIC-server

WebTransport

Bidirectionele streams en datagrammen naar een browser via HTTP/3, afgeschermd door SGC_WEBTRANSPORT op regel 898. Er worden twee demo's meegeleverd.

sgcQUIC-functies

HTTP/3 ontdekken vanuit HTTP/2

Een server kondigt HTTP/3 aan met een Alt-Svc-header. Handel OnAltSvc af en je kunt een bestaande verbinding upgraden naar QUIC wanneer de origin dat aanbiedt.

HTTP/2-client

Referentie, demo's en documentatie

Demoprojecten zitten in de download, onder Demos\22.QUIC_Protocol. Het zijn er zes.

HTTP/3-clientcomponent Wat TsgcHTTP3Client beschikbaar stelt, eigenschap voor eigenschap.
HTTP/3-servercomponent De serverkant, inclusief de OpenSSL 3.5-vereiste.
QUIC-clientcomponent Pure QUIC-streams zonder de HTTP/3-laag.
sgcQUIC-functies QPACK, 0-RTT, verbindingsmigratie, WebTransport en de rest.
Download de proefversie Eén installatieprogramma per IDE-versie, met de QUIC-componenten er al in.
Online help De gegenereerde referentie, altijd in lijn met de huidige release.

Verder lezen: de QUIC-client- en servercomponenten en de HTTP/3-componenten. Als je kiest tussen transporten, vergelijkt de gids voor realtime transport ze. Elk product heeft zijn eigen snelstart, te vinden op de pagina Aan de slag.

Vragen over de sgcQUIC-snelstart

TsgcHTTP3Client, uit de unit sgcQUIC, op de palettabpagina SGC QUIC. Voeg sgcHTTP3_Classes toe voor TsgcHTTP3Response, het parametertype van OnResponse, en sgcHTTP_AltSvc als je OnAltSvc afhandelt. De palettabpagina bevat ook TsgcQUICClient, TsgcQUICServer and TsgcHTTP3Server.
Het hangt ervan af welke kant je bouwt. De client heeft de QUIC-API nodig die in OpenSSL 3.2 is toegevoegd, of een quictls-build, en de bibliotheek zegt dat in de melding die ze veroorzaakt: QUIC is not available. Requires quictls/openssl or OpenSSL 3.2+. De server heeft 3.5 of hoger nodig, omdat die SSL_new_listener aanroept, en de foutmelding noemt die versie uitdrukkelijk. Lever libcrypto-3.dll en libssl-3.dll mee naast je uitvoerbare bestand. msquic wordt niet gebruikt.
Omdat ze alleen-lezen zijn. TsgcHTTP3Client declareert ze als property Host: string read FHost en property Port: Integer read FPort, dus ze rapporteren de huidige verbinding in plaats van die te configureren. Geef een volledige URL mee aan Get, Post, Put of Delete, of roep eerst Connect(const aHost: string; aPort: Integer = 443) aan.
Een gewone TNotifyEvent, dus procedure(Sender: TObject). Hetzelfde geldt voor OnDisconnect. Dit verschilt van de WebSocket-componenten, waarvan de gebeurtenissen je een TsgcWSConnection geven, en het is een veelvoorkomende bron van een eerste compilerfout. OnResponse is procedure(Sender: TObject; const aResponse: TsgcHTTP3Response) and OnError is procedure(Sender: TObject; const aError: string).
Uit het responsobject op OnResponse. TsgcHTTP3Response stelt StatusCode beschikbaar, Headers als TStringList en GetDataAsString voor de body. De methode Get zelf geeft alleen de body terug als string, en daarom koppelt de demo ook OnResponse.
SGC_PACK_QUIC wordt gedefinieerd op regel 872 van sgcVer.inc, binnen het {$IFDEF SGC_EDT_ALL}-blok dat loopt van regel 870 tot regel 874. Dus All-Access. Het packblok zelf, regel 894 tot 899, staat ook binnen een {$IFDEF SGC_INDY_LIB}, dus de aangepaste Indy-bibliotheek moet ook deel uitmaken van de build. Binnen dat blok is SGC_QUIC regel 896, SGC_HTTP3 regel 897 en SGC_WEBTRANSPORT regel 898.
Nee. Het installatieprogramma van de proefversie is per IDE-versie en bevat de QUIC- en HTTP/3-componenten al, en er is geen QUIC-specifiek packagebestand. Installeer sgcWebSockets en de palettabpagina SGC QUIC verschijnt wanneer de editie die inschakelt.
Ja, en dat zou je moeten doen. IsOpenSSL_QUIC_Available geeft terug of de geladen OpenSSL de QUIC-clientmethode beschikbaar stelt en IsOpenSSL_QUIC_TLS_Available doet hetzelfde voor de QUIC-TLS-callbacks. De meegeleverde QUIC-clientdemo schrijft beide bij het opstarten naar zijn log, waardoor een raadselachtige verbindingsfout een antwoord van één regel wordt.
De beste deal: All-AccessElk eSeGeCe-product, inclusief Premium-ondersteuning, vanaf €1,059 per jaar.
Bekijk de All-Access-prijzen

Klaar om HTTP/3 uit te proberen vanuit Delphi?

Download de proefversie en draai de HTTP/3-clientdemo tegen een echte origin.