sgcQUIC en cinco minutos

QUIC y HTTP/3 en Object Pascal nativo, sobre el motor QUIC incluido en OpenSSL. Se incluyen cuatro componentes. El camino más corto para tener algo funcionando es el cliente HTTP/3, así que esta página hace una petición, lee el código de estado y es precisa sobre qué OpenSSL necesitas.

QUIC RFC 9000 y HTTP/3 RFC 9114
OpenSSL 3.2 y posteriores para el cliente
Edición All-Access

Lo que necesita la primera petición

Un componente, una URL y dos bibliotecas OpenSSL junto a tu ejecutable.

Componente

TsgcHTTP3Client en la página SGC QUIC de la paleta, declarado en sgcQUIC.pas. La página incluye también TsgcQUICClient, TsgcQUICServer y TsgcHTTP3Server.

Unit

sgcQUIC para el componente. Añade sgcHTTP3_Classes para TsgcHTTP3Response, y sgcHTTP_AltSvc si gestionas el evento Alt-Svc.

La llamada

Get(aURL) devuelve el cuerpo como un string y lanza una excepción si falla. El código de estado y las cabeceras llegan por separado, en OnResponse.

El requisito de OpenSSL

El cliente necesita la API QUIC de OpenSSL 3.2 o posterior, o una compilación de quictls. El servidor necesita la 3.5 o posterior, porque llama a una API que solo existe ahí. Distribuye libcrypto-3.dll y libssl-3.dll junto a tu ejecutable, como hace cada carpeta de demo.

Requisitos y ediciones

La columna de edición es el define que controla el código, con la línea en la que se encuentra en Source/sgcVer.inc.

Qué Valor
IDE Delphi 7 hasta RAD Studio 13, y C++Builder 2007 hasta 13. No hay una descarga separada de sgcQUIC: los componentes están en el grupo de paquetes de sgcWebSockets.
Cláusula uses sgcQUIC, más sgcHTTP3_Classes para el objeto de respuesta y sgcHTTP_AltSvc para los tipos de Alt-Svc.
Define del paquete SGC_PACK_QUIC se define en la línea 872, dentro del bloque {$IFDEF SGC_EDT_ALL} que va de la línea 870 a la 874. Es decir, All-Access.
Defines de características Dentro del bloque {$IFDEF SGC_PACK_QUIC} en las líneas 894 a 899: SGC_QUIC en la línea 896, SGC_HTTP3 en la línea 897 y SGC_WEBTRANSPORT en la línea 898. Los tres están dentro de un {$IFDEF SGC_INDY_LIB} en la línea 895, así que una compilación sin la biblioteca Indy personalizada no obtiene ninguno.
OpenSSL, cliente 3.2 o posterior, o una compilación de quictls. La propia biblioteca lo dice: el error que se lanza cuando QUIC no está disponible dice QUIC is not available. Requires quictls/openssl or OpenSSL 3.2+.
OpenSSL, servidor 3.5 o posterior. El servidor QUIC llama a SSL_new_listener, y el error que lanza cuando falta dice QUIC Server requires OpenSSL 3.5 or later. msquic no se usa y no hace falta.
Plataformas No hay guarda de plataforma a nivel de unit en sgcQUIC.pas, sgcQUIC_Client.pas, sgcHTTP3_Client.pas ni sgcHTTP3_Server.pas, y los cuatro componentes se registran con ComponentPlatforms(0). La unit del servidor selecciona la API de sockets según la plataforma, con una rama para Windows y otra para POSIX.

¿No estás seguro de que el motor esté presente en tiempo de ejecución? Llama a IsOpenSSL_QUIC_Available, que indica si el OpenSSL que has cargado expone el método de cliente QUIC. La demo de cliente QUIC incluida lo registra al arrancar precisamente por eso.

Instala y localiza la página de la paleta

No hay un instalador de sgcQUIC aparte. Los componentes llegan con sgcWebSockets y aparecen cuando la edición los habilita.

1. Descomprime

Descomprime la descarga de sgcWebSockets en una carpeta, llamada {$DIR} más abajo.

2. Ruta de biblioteca

Tools, Options, Library. Añade {$DIR}\source y la carpeta lib de tu IDE, por ejemplo {$DIR}\libD13\$(Platform).

3. Compila los paquetes

Abre el grupo de paquetes de tu versión de IDE en {$DIR}\Packages\. Compila primero el .dpk de runtime y después instala el de tiempo de diseño, el dcl. No hay un paquete específico de QUIC.

4. Comprueba la paleta

Aparece una página llamada SGC QUIC con TsgcQUICClient, TsgcQUICServer, TsgcHTTP3Client y TsgcHTTP3Server. Si falta la página, la compilación no es All-Access, porque SGC_PACK_QUIC se define solo en la línea 872 dentro de ese bloque.

5. Pon OpenSSL junto al exe

Copia libcrypto-3.dll y libssl-3.dll junto a tu ejecutable, la 3.2 o posterior para un cliente y la 3.5 o posterior para un servidor. Cada carpeta de Demos\22.QUIC_Protocol las incluye, así que puedes copiarlas de ahí.

Una petición HTTP/3

Crea el cliente, conecta tres eventos y llama a Get. La respuesta vuelve como una cadena y el código de estado llega en 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 y Delete tienen la misma forma, y cada uno tiene una sobrecarga con stream para un cuerpo que no quieres mantener en una cadena. Connect(const aHost: string; aPort: Integer = 443) abre la conexión antes de la primera petición cuando quieres separar ambas cosas.

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;

Leer FClient.Host y FClient.Port dentro de OnConnect es exactamente para lo que sirven esas dos propiedades. Informan de la conexión, no la configuran.

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;

Ejecútalo una vez antes que nada. Si ambos devuelven false, el OpenSSL junto a tu ejecutable no tiene QUIC, y cada fallo de conexión posterior es un síntoma de este único hecho y no de la red.

Las dos primeras pestañas proceden de la demo incluida Demos\22.QUIC_Protocol\03.HTTP3_Client\FHTTP3Client.pas, con los controles del formulario sustituidos por literales. La tercera es la comprobación de disponibilidad en tiempo de ejecución de 01.QUIC_Client\FQUICClient.pas. Hay seis demos de QUIC en esa carpeta, incluida una pareja de WebTransport.

Lee el código de estado, no solo el cuerpo

Get devuelve el cuerpo. El objeto de respuesta lleva todo lo demás, y llega en su propio evento.

El valor de retorno

Get devuelve el cuerpo de la respuesta como un string y lanza una excepción si falla, por eso la demo lo envuelve en un try except. Un cuerpo de la longitud esperada es la primera prueba.

OnResponse

procedure(Sender: TObject; const aResponse: TsgcHTTP3Response). StatusCode es el número que realmente quieres, Headers es un TStringList y GetDataAsString te devuelve de nuevo el cuerpo desde el objeto de respuesta.

OnConnect

Un TNotifyEvent normal. Que se dispare significa que QUIC negoció y la sesión HTTP/3 se abrió, que es la parte con más probabilidades de fallar en una primera ejecución.

Antes de culpar al código

IsOpenSSL_QUIC_Available responde a la única pregunta que merece la pena hacer primero. QUIC además funciona sobre UDP 443, y una red que permite TCP 443 no necesariamente permite eso.

Lo que suele fallar la primera vez

Seis problemas explican casi todas las primeras peticiones fallidas.

No se puede asignar Host ni Port

Son de solo lectura en TsgcHTTP3Client, declaradas como property Host: string read FHost y property Port: Integer read FPort. Informan de dónde está conectado el cliente. Para elegir un destino, pasa una URL completa a Get o llama a Connect(aHost, aPort).

QUIC no está disponible

El OpenSSL que has cargado es demasiado antiguo o se compiló sin QUIC. El cliente necesita la 3.2 o posterior, o quictls. Comprueba en tiempo de ejecución con IsOpenSSL_QUIC_Available antes de culpar a la red.

El servidor no arranca

El servidor QUIC necesita OpenSSL 3.5 o posterior, porque llama a SSL_new_listener. Una compilación 3.2 basta para el cliente y no para el servidor, y el mensaje de error lo dice explícitamente.

Número de parámetros incorrecto en OnConnect

OnConnect y OnDisconnect en este componente son TNotifyEvent normales, así que el manejador solo recibe Sender: TObject. No te entregan un objeto de conexión, a diferencia de los componentes WebSocket.

UDP está bloqueado

QUIC funciona sobre UDP en el puerto 443, y muchas redes corporativas permiten TCP 443 y descartan UDP 443. Si un navegador llega al host por HTTP/3 y tu aplicación no, sospecha del firewall antes que del código.

Falta la página de la paleta

SGC_PACK_QUIC se define solo en la línea 872, dentro del bloque All-Access. Además requiere SGC_INDY_LIB, porque todo el bloque del paquete de las líneas 894 a 899 está dentro de esa guarda.

Más allá de la primera petición

Cuatro direcciones, todas dentro del mismo paquete.

Ejecuta un servidor HTTP/3

TsgcHTTP3Server sirve HTTP/3 directamente sobre QUIC. Recuerda el mínimo de OpenSSL 3.5 en el lado del servidor.

Componente servidor HTTP/3

QUIC puro, sin HTTP

TsgcQUICClient y TsgcQUICServer te dan streams QUIC sin la capa HTTP/3, que es lo que quieres para un protocolo propio que necesita multiplexación sin bloqueo de cabecera de línea.

Cliente QUIC y servidor QUIC

WebTransport

Streams bidireccionales y datagramas hacia un navegador sobre HTTP/3, controlados por SGC_WEBTRANSPORT en la línea 898. Se incluyen dos demos.

Características de sgcQUIC

Descubre HTTP/3 desde HTTP/2

Un servidor anuncia HTTP/3 con una cabecera Alt-Svc. Gestiona OnAltSvc y podrás actualizar una conexión existente a QUIC cuando el origen lo ofrezca.

Cliente HTTP/2

Referencia, demos y documentación

Los proyectos de demo se incluyen dentro de la descarga, en Demos\22.QUIC_Protocol. Hay seis.

Componente cliente HTTP/3 Lo que expone TsgcHTTP3Client, propiedad por propiedad.
Componente servidor HTTP/3 El lado del servidor, incluido el requisito de OpenSSL 3.5.
Componente cliente QUIC Streams QUIC puros sin la capa HTTP/3.
Características de sgcQUIC QPACK, 0-RTT, migración de conexión, WebTransport y el resto.
Descarga la versión de prueba Un instalador por versión de IDE, con los componentes QUIC ya incluidos.
Ayuda en línea La referencia generada, siempre al día con la versión actual.

Lecturas relacionadas: los componentes cliente y servidor QUIC y los componentes HTTP/3. Si estás eligiendo entre transportes, la guía de transportes en tiempo real los compara. Cada producto tiene su propio inicio rápido, listado en la página de primeros pasos.

Preguntas sobre el inicio rápido de sgcQUIC

TsgcHTTP3Client, de la unit sgcQUIC, en la página SGC QUIC de la paleta. Añade sgcHTTP3_Classes para TsgcHTTP3Response, que es el tipo del parámetro de OnResponse, y sgcHTTP_AltSvc si gestionas OnAltSvc. La página de la paleta incluye también TsgcQUICClient, TsgcQUICServer y TsgcHTTP3Server.
Depende de qué lado estés construyendo. El cliente necesita la API QUIC añadida en OpenSSL 3.2, o una compilación de quictls, y la biblioteca lo dice en el mensaje que lanza: QUIC is not available. Requires quictls/openssl or OpenSSL 3.2+. El servidor necesita la 3.5 o posterior, porque llama a SSL_new_listener, y su mensaje de error nombra esa versión explícitamente. Distribuye libcrypto-3.dll y libssl-3.dll junto a tu ejecutable. msquic no se usa.
Porque son de solo lectura. TsgcHTTP3Client las declara como property Host: string read FHost y property Port: Integer read FPort, así que informan de la conexión actual en lugar de configurarla. Pasa una URL completa a Get, Post, Put o Delete, o llama primero a Connect(const aHost: string; aPort: Integer = 443).
Un TNotifyEvent normal, es decir, procedure(Sender: TObject). Lo mismo para OnDisconnect. Esto difiere de los componentes WebSocket, cuyos eventos te entregan un TsgcWSConnection, y es una fuente habitual de un primer error de compilación. OnResponse es procedure(Sender: TObject; const aResponse: TsgcHTTP3Response) y OnError es procedure(Sender: TObject; const aError: string).
Desde el objeto de respuesta en OnResponse. TsgcHTTP3Response expone StatusCode, Headers como un TStringList y GetDataAsString para el cuerpo. El propio método Get devuelve solo el cuerpo como cadena, y por eso la demo conecta también OnResponse.
SGC_PACK_QUIC se define en la línea 872 de sgcVer.inc, dentro del bloque {$IFDEF SGC_EDT_ALL} que va de la línea 870 a la 874. Es decir, All-Access. El propio bloque del paquete, líneas 894 a 899, también está dentro de un {$IFDEF SGC_INDY_LIB}, así que la biblioteca Indy personalizada también tiene que formar parte de la compilación. Dentro de ese bloque, SGC_QUIC es la línea 896, SGC_HTTP3 es la línea 897 y SGC_WEBTRANSPORT es la línea 898.
No. El instalador de prueba es por versión de IDE y ya contiene los componentes QUIC y HTTP/3, y no existe un archivo de paquete específico de QUIC. Instala sgcWebSockets y la página SGC QUIC de la paleta aparece cuando la edición la habilita.
Sí, y deberías. IsOpenSSL_QUIC_Available indica si el OpenSSL cargado expone el método de cliente QUIC, e IsOpenSSL_QUIC_TLS_Available hace lo mismo para los callbacks TLS de QUIC. La demo de cliente QUIC incluida escribe ambos en su log al arrancar, lo que convierte un misterioso fallo de conexión en una respuesta de una línea.
La mejor opción: All-AccessTodos los productos de eSeGeCe, con Premium Support incluido, desde €1,059 al año.
Ver precios de All-Access

¿Listo para probar HTTP/3 desde Delphi?

Descarga la versión de prueba y ejecuta la demo del cliente HTTP/3 contra un origen real.