sgcWebSockets HTTP and Transports
Everything in this skill speaks HTTP or sits directly on the transport beneath it: HTTP/2 and HTTP/3 clients, QUIC, gRPC, a REST server with its companions, plain TCP and UDP, and the WebView2 control.
Unlike most skills here, these components do not share a unit. Check the
unit: line on each API page before writing the uses clause.
When to use this skill
- Make HTTP/2 or HTTP/3 requests, synchronously or asynchronously
- Run a REST server, with sessions, CORS, static files, users and multi-tenancy
- Call a gRPC service, including streaming in either direction
- Open a raw QUIC connection
- Serve an OpenAPI-described API from a WebSocket server
- Use plain TCP or UDP sockets with the same component style
- Embed a Chromium browser with WebView2
For WebSocket itself load sgcwebsockets-core. For OAuth2 and JWT load
sgcwebsockets-auth, they are frequently used with the REST server here.
Units, one per component group
| Unit | Components |
|---|---|
sgcHTTP |
TsgcHTTP2Client, TsgcGRPCClient |
sgcQUIC |
TsgcQUICClient, TsgcQUICServer, TsgcHTTP3Client, TsgcHTTP3Server |
sgcHTTP_REST_Server |
TsgcHTTPRESTServer |
sgcHTTP_REST_Server_Users |
TsgcHTTPServer_Users |
sgcHTTP_REST_Server_Tenancy |
TsgcHTTPServer_Tenancy |
sgcHTTP_REST_Server_Stats |
TsgcHTTPServerStats |
sgcTCP_Client_WS |
TsgcTCPClient |
sgcP2P |
TsgcUDPCLient, TsgcUDPServer |
sgcWebSocket_Server_API_OpenAPI |
TsgcWSAPIServer_OpenAPI |
sgcWebView2 |
TsgcWebView2 |
TsgcUDPCLient is spelled with a capital L in the middle. That is the actual
component name, not a typo in this document.
Before you start, ask the developer
Use a structured question tool if your host has one, for example Claude Code's
AskUserQuestion. Otherwise ask in chat:
- Blocking or async? The HTTP/2 client offers both for every verb:
Getreturns the body as a string,GetAsyncreturns immediately and reports through events. Mixing the two styles in one flow is the usual source of confusion. - HTTP/2 or HTTP/3? They are different components with different bodies:
HTTP/2
Posttakes aTStream, HTTP/3Posttakes a string. HTTP/3 also needs QUIC, which is UDP, so corporate firewalls may block it. - Which Delphi version? QUIC and HTTP/3 have a higher version floor than the rest of the suite.
- Does the REST server need sessions, users or tenancy? Those are separate companion components you attach, not switches on the server.
Components in this skill
| Component | Use it for |
|---|---|
TsgcHTTP2Client |
HTTP/2 requests, sync and async, stream bodies |
TsgcHTTP3Client |
HTTP/3 requests over QUIC, string bodies |
TsgcHTTP3Server |
Serving HTTP/3 |
TsgcQUICClient / TsgcQUICServer |
Raw QUIC, below HTTP/3 |
TsgcGRPCClient |
gRPC unary and streaming calls |
TsgcHTTPRESTServer |
REST/HTTP server with sessions, CORS, static files |
TsgcHTTPServer_Users |
User accounts for the REST server |
TsgcHTTPServer_Tenancy |
Multi-tenant routing for the REST server |
TsgcHTTPServerStats |
Request and connection statistics |
TsgcWSAPIServer_OpenAPI |
Serves an OpenAPI-described API |
TsgcTCPClient |
Plain TCP client |
TsgcUDPCLient / TsgcUDPServer |
Plain UDP |
TsgcWebView2 |
Embedded Chromium via WebView2 |
Quickstart, HTTP/2 client
Every verb comes as a blocking function and an ...Async procedure:
uses
sgcHTTP;
var
vResponse: string;
oBody: TStringStream;
begin
FHTTP2 := TsgcHTTP2Client.Create(Self);
// blocking: returns the response body
vResponse := FHTTP2.Get('https://example.com/api/items');
// POST and PUT take a stream, not a string
oBody := TStringStream.Create('{"name":"test"}', TEncoding.UTF8);
try
vResponse := FHTTP2.Post('https://example.com/api/items', oBody);
finally
oBody.Free;
end;
end;
For the non-blocking style call GetAsync or PostAsync and handle the
response event instead. PostAsync takes a correlation id so you can match a
reply to the request that caused it.
Quickstart, HTTP/3 client
HTTP/3 connects to a host and port first, and its bodies are strings:
uses
sgcQUIC;
FHTTP3 := TsgcHTTP3Client.Create(Self);
FHTTP3.Connect('example.com', 443);
if FHTTP3.Connected then
begin
vResponse := FHTTP3.Get('/api/items');
vResponse := FHTTP3.Post('/api/items', '{"name":"test"}', 'application/json');
end;
Quickstart, REST server
There is no declarative route table. The server dispatches through two Indy
style events, so you inspect the path yourself. The split is not the obvious
one: OnCommandGet receives GET, POST and HEAD, and OnCommandOther
receives everything else, so PUT, DELETE, PATCH and OPTIONS. Putting a POST
handler in OnCommandOther is a common mistake and it simply never fires:
uses
sgcHTTP_REST_Server, IdContext, IdCustomHTTPServer;
FREST := TsgcHTTPRESTServer.Create(Self);
FREST.Port := 8080;
FREST.DocumentRoot := 'C:\www'; // static files, optional
FREST.OnCommandGet := RESTCommandGet;
FREST.Active := True;
procedure TForm1.RESTCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
if ARequestInfo.Document = '/api/time' then
begin
AResponseInfo.ContentType := 'application/json';
AResponseInfo.ContentText := '{"now":"' + DateTimeToStr(Now) + '"}';
AResponseInfo.ResponseNo := 200;
end
else
AResponseInfo.ResponseNo := 404;
end;
The handler signature is Indy's, so IdContext and IdCustomHTTPServer belong
in your uses clause even though the component is an sgc one.
Note that POST arrives in OnCommandGet alongside GET, so branch on
ARequestInfo.CommandType or ARequestInfo.Command when a path accepts both.
Sessions, CORS, compression and body limits are properties on the server:
AutoStartSession, CORSOptions, HTTPCompression, MaxRequestBodySize and
StrictRequestParsing. Users, tenancy and statistics are separate components
you attach through the matching properties.
Quickstart, gRPC
gRPC works in bytes, because the payload is protobuf that you encode yourself:
uses
sgcHTTP;
var
oResponse: TsgcGRPCResponse;
begin
FGRPC := TsgcGRPCClient.Create(Self);
oResponse := FGRPC.Call('helloworld.Greeter', 'SayHello', vRequestBytes);
end;
ServerStreamingCall handles a stream of replies. For client streaming, open
with OpenClientStream, push with SendStreamMessage, and finish with
CloseClientStream, which returns the response.
Things that catch people out
- HTTP/2
PostandPuttake aTStream. Passing a string will not compile, and the fix is aTStringStreamyou own and free. - HTTP/3 runs over QUIC, which is UDP. If it fails everywhere except your machine, suspect a firewall before suspecting the code.
- The REST server's request handlers use Indy types. Forgetting
IdContextandIdCustomHTTPServerinusesproduces errors that look like the component is broken. DocumentRootserves static files. If a file on disk shares a path with an endpoint you handle in code, decide deliberately which one you want to win.- The async HTTP/2 calls return immediately. Reading the response variable on the next line gets you the previous value, or an empty string.
Routing
- Find a component:
reference/components-index.mdlists every component, itsunit, and its edition, grouped by Reg module. - Uses clause: add the component's
unit:value (shown on its API page) to yourusesclause. Nothing compiles without it. - API detail:
reference/api/<Component>.mdhas the Properties, Events and Methods, each in both Delphi and C++Builder form. - Option / enum / event types: property and event types link to
reference/types/<TypeName>.md, which documents the sub-properties of option classes, the values of enums, and the parameter list of event handlers. - Examples:
examples/index.mdis the full demo catalog;examples/<Component>.mdis a focused, real usage snippet for the most-used components. - Concepts:
concepts/overview.md(getting started + uses-clause rule) andconcepts/editions-and-features.md(which components your edition includes). - Bundled resources:
concepts/resources.mdlists the browser-side assets (JavaScript, HTML, CSS) the server components serve or embed, so a browser client works without an external CDN. - Version history:
reference/history.mdlists what changed in each sgcWebSockets release.
Editions
Components are gated by edition (Professional, Enterprise, All-Access) or by a feature define. Check the edition column in the components index, or concepts/editions-and-features.md, before relying on a component.
Only public and published members are documented. Method bodies, private fields and protected members are intentionally not included.