sgcWebSockets 2026.5 è una release ricca di contenuti. Tre nuovi componenti infrastrutturali trasformano il server WebSocket / HTTP in un API gateway di livello produttivo: un rate limiter completo, un circuit breaker lato client e un gestore di chiavi API con supporto completo del ciclo di vita. Sul fronte protocolli arriva un nuovo client Forex.com basato su un'implementazione generica di Lightstreamer TLCP 2.5, l'MCP Server acquisisce un flusso OAuth 2.1 integrato così da poter connettersi direttamente a client MCP basati su browser come claude.ai, e i motori I/O IOCP (Windows) e EPOLL (Linux) ricevono sei miglioramenti misurabili delle prestazioni. C'è anche una primitiva post-quantum in anteprima: sgcKEM_CreateMLKEM768Keys per la generazione di coppie di chiavi ML-KEM-768.
Questo post illustra i punti salienti con snippet Delphi pronti da incollare per i nuovi componenti.
TsgcWSRateLimiter — rate limiting API pronto all'uso
Aggiungi un TsgcWSRateLimiter accanto al tuo server e avrai rate limiting token-bucket, sliding-window o fixed-window per IP, per chiave API, per utente o per pattern di endpoint, oltre a quote giornaliere/mensili e protezione dai burst. Il componente è thread-safe e persiste lo stato su disco (in modo che un riavvio del server non conceda a ogni client una nuova quota).
uses
sgcWebSocket_Server_RateLimiter;
var
oRL: TsgcWSRateLimiter;
oResult: TsgcRateLimitResult;
begin
oRL := TsgcWSRateLimiter.Create(nil);
try
oRL.TokenBucket.Enabled := True;
oRL.TokenBucket.Capacity := 100; // burst size
oRL.TokenBucket.RefillRate := 10; // tokens / interval
oRL.TokenBucket.RefillIntervalMs := 1000;
oRL.PerIP.Enabled := True;
oRL.PerIP.MaxRequests := 60;
oRL.PerIP.WindowSec := 60;
// Consume one token for the current request
oResult := oRL.Consume('ip:' + vClientIP);
if not oResult.Allowed then
RespondHTTP(429, 'Retry-After: ' + IntToStr(oResult.RetryAfterSec));
finally
oRL.Free;
end;
end;
Il resolver delle regole percorre PerEndpoint (con corrispondenza wildcard), poi PerAPIKey, PerUser e infine PerIP. Gli eventi OnThrottled, OnQuotaExceeded e OnStateChange ti permettono di registrare o sovrascrivere ogni decisione.
Demo: Demos\04.WebSocket_Other_Samples\14.RateLimiter — esegue un client che genera flood contro un server che pubblica statistiche dal vivo e motivi di rifiuto.
TsgcWSCircuitBreaker — isolamento dei guasti lato client
Quando un'API a monte (api.openai.com, un gateway di pagamento, un microservizio interno) inizia a fallire o a rallentare, restare appesi ai timeout TCP costa connessioni, thread e denaro. TsgcWSCircuitBreaker implementa il classico pattern a tre stati (closed / open / half-open) sopra qualunque sottoclasse di TsgcHTTPAPI_client, con una finestra temporale scorrevole, rilevamento delle chiamate lente, risposte di fallback opzionali e override per endpoint.
uses
sgcWebSocket_CircuitBreaker;
var
oCB: TsgcWSCircuitBreaker;
begin
oCB := TsgcWSCircuitBreaker.Create(nil);
try
oCB.Thresholds.FailureCount := 5;
oCB.Thresholds.FailureRatePercent := 50;
oCB.Thresholds.SlowCallDurationMs := 2000;
oCB.Thresholds.SlowCallRatePercent := 80;
oCB.TimeWindow.RollingWindowSec := 60;
oCB.Recovery.CooldownSec := 30;
oCB.Recovery.HalfOpenTrialCalls := 3;
oCB.Fallback.Enabled := True;
oCB.Fallback.UseLastSuccess := True;
if oCB.IsCallAllowed('openai') then
try
vResponse := oOpenAI.ChatCompletion(...);
oCB.RecordSuccess('openai');
except
on E: Exception do
begin
oCB.RecordFailure('openai', E.ClassName);
raise;
end;
end
else
vResponse := 'service temporarily unavailable';
finally
oCB.Free;
end;
end;
Su Delphi 2009+ è disponibile anche un wrapper a una sola riga: oCB.Execute('openai', procedure begin oOpenAI.ChatCompletion(...) end); — la registrazione di successo / fallimento avviene automaticamente.
Demo: Demos\04.WebSocket_Other_Samples\15.CircuitBreaker.
TsgcWSAPIKeyManager — ciclo di vita delle chiavi in un solo componente
La maggior parte dei server "WebSocket API" ha bisogno di chiavi API: emettere, validare, revocare, ruotare. TsgcWSAPIKeyManager incapsula l'intero ciclo di vita con autorizzazione basata su scope, hashing opzionale a riposo, scadenza, log di audit e un periodo di grazia per la rotazione integrato, così che le vecchie chiavi continuino a funzionare per una finestra configurabile dopo la rotazione.
uses
sgcWebSocket_Server_APIKeyManager;
var
oKM: TsgcWSAPIKeyManager;
vKey, vNewKey: string;
begin
oKM := TsgcWSAPIKeyManager.Create(nil);
try
oKM.Generation.Length := 40;
oKM.Generation.Prefix := 'sgc_';
oKM.Hashing.Enabled := True; // store SHA-256 hash, not the plaintext
oKM.Rotation.GracePeriodSec := 86400; // old key valid for 24h after rotation
oKM.Expiration.DefaultTTLSec := 30 * 86400;
// Issue a key for tenant "acme" with read+write scopes, expiring in 7 days
vKey := oKM.IssueKey('acme', ['read', 'write'], 7 * 86400);
// Validate the key on each request, optionally requiring a scope
if not oKM.ValidateKey(vKey, 'read', vClientIP) then
RespondHTTP(401, 'invalid api key');
// Rotate a key (returns the new plaintext; old key remains valid for GracePeriodSec)
oKM.RotateKey(vKey, vNewKey);
finally
oKM.Free;
end;
end;
Il componente può leggere la chiave direttamente dagli header HTTP in ingresso o dalla query string con IsRequestAuthorized, così non devi cablare tu stesso l'estrazione.
Demo: Demos\04.WebSocket_Other_Samples\16.APIKeyManager.
Client Forex.com + Lightstreamer generico
Il nuovo client TsgcWSAPI_Forex offre accesso unificato REST + streaming a Forex.com (login, ping, market watch, posizioni, ordini, storico operazioni, simulazione operazioni). È costruito su un nuovo componente TsgcWSPClient_Lightstreamer, un client Lightstreamer TLCP 2.5 generico che implementa create_session, bind_session, control (subscribe / unsubscribe) e il riassociamento automatico LOOP + replay delle sottoscrizioni dopo la riconnessione. Il client Lightstreamer è riutilizzabile in modo autonomo, quindi la stessa base di codice funziona con IG Markets e con qualsiasi altro feed basato su Lightstreamer.
uses sgcHTTP_API_Forex;
var oFX: TsgcWSAPI_Forex;
begin
oFX := TsgcWSAPI_Forex.Create(nil);
oFX.UserName := 'demo-user';
oFX.Password := 'secret';
oFX.AppKey := 'your-app-key';
oFX.Login;
oFX.SubscribePrices(['EUR/USD', 'GBP/USD', 'XAU/USD']);
oFX.OnPriceUpdate := procedure(const aSymbol: string; aBid, aAsk: Double)
begin
ShowMessage(Format('%s %.5f / %.5f', [aSymbol, aBid, aAsk]));
end;
end;
Una demo GUI completa è in Demos\05.Crypto\22.Forex — login, ping di connettività, market watch dal vivo, posizioni, ordini attivi, storico operazioni, storico stop / limit e simulazione operazioni, con credenziali persistite in sgcForexDemo.ini.
MCP Server — OAuth 2.1 per client MCP basati su browser
L'MCP Server può ora dialogare direttamente con connettori MCP basati su browser (come claude.ai) senza un authorization server esterno. Pubblica automaticamente i quattro endpoint di discovery / registrazione OAuth richiesti dalla specifica del connettore browser MCP, esegue un flusso di autorizzazione PKCE-S256 con schermata di consenso HTML ed emette refresh token:
GET /.well-known/oauth-authorization-server— metadati RFC 8414.GET /.well-known/oauth-protected-resource— metadati di risorsa protetta RFC 9728.POST /oauth/register— registrazione dinamica del client RFC 7591.GET /oauth/authorize— modulo di consenso HTML.POST /oauth/token— PKCE S256 + refresh token.
Il CORS è gestito inline: il preflight OPTIONS restituisce 204 con header Access-Control-* completi prima dell'autenticazione, ogni risposta porta un Access-Control-Allow-Origin che riflette l'origin della richiesta e un header HSTS Strict-Transport-Security: max-age=31536000.
IOCP ed EPOLL: sei miglioramenti di tuning
I motori I/O IOCP su Windows ed EPOLL su Linux hanno ricevuto un giro mirato di lavoro su prestazioni e tunability.
IOCP (Windows)
ThreadAffinity(defaultFalse) suTsgcIndy_IO_Engine— aggancia i thread del motore in round-robin ai core logici tramiteSetThreadAffinityMask. Riduce il traffico di cache cross-core sui sistemi con molti core.Metrics— un nuovo recordTsgcIndy_IO_EngineMetrics(AcceptsPosted,AcceptsCompleted,ReadsPosted,ReadsCompleted,ActiveConnections,BytesRead,BytesWritten) aggiornato sotto una sezione critica. Niente più tentativi a indovinare.SendBufferSize,ReceiveBufferSize,TCPNoDelaysuTsgcIndy_IOHandler_IO_IOCP— applicati inAfterAccepttramitesetsockopt, così il tuning per connessione non richiede più un handlerOnConnectpersonalizzato.TsgcPerIoDataPoolcapacità aumentata da 256 a 2048, evitando il fallback heapGetMem/FreeMemcon elevata concorrenza di connessioni. +15–18% di throughput WebSocket nei benchmark su loopback.
oServer.Bindings.Add.Port := 443;
oServer.IOHandler := TsgcIndy_IOHandler_IO_IOCP.Create(oServer);
with TsgcIndy_IOHandler_IO_IOCP(oServer.IOHandler) do
begin
SendBufferSize := 256 * 1024;
ReceiveBufferSize := 256 * 1024;
TCPNoDelay := True;
Engine.ThreadAffinity := True;
end;
EPOLL (Linux)
AcceptBatchSize,WaitTimeoutMS,HandshakeTimeoutMS— consentono di regolare il ciclo di accept e la protezione slow-loris.- Backpressure in scrittura guidata da EPOLLOUT — quando
send()restituisceEAGAINsu una scrittura parziale, i byte rimanenti vengono catturati in un buffer pending per connessione e il socket viene ri-armato conEPOLLIN|EPOLLOUT. Il reattore svuota la coda al successivo eventoEPOLLOUTinvece di scartare i byte o bloccare il worker.
Condivisi
Il pool di worker IOCP / EPOLL eseguiva sleep(1) a ogni iterazione, incluso subito dopo aver elaborato un task — di fatto limitando ciascun worker a ~1.000 ops/s anche con la coda piena. Lo sleep viene ora saltato finché c'è lavoro in attesa, eliminando il limite.
HTTP.sys: modalità ad alte prestazioni opt-in
Il server HTTP.sys acquisisce una proprietà FineTune con un selettore OperatingMode. Il valore predefinito ompClassic preserva il comportamento esistente. La nuova modalità ompHighPerf implementa il pattern MSDN N-worker × M-receive asincroni pre-postati — l'architettura raccomandata per i deployment HTTP.sys ad alto throughput — dietro un'unica proprietà:
oServer := TsgcWebSocketHTTPServer.Create(nil);
oServer.HTTP2Options.SecureOptions.HTTPAPI := True; // use HTTP.sys
oServer.FineTune.OperatingMode := ompHighPerf;
oServer.FineTune.WorkerCount := 8;
oServer.FineTune.PrePostedReceivesPerWorker := 16;
oServer.Active := True;
Anche THttpServerRequest e THttpServerResponse sono stati estesi con campi aggiuntivi che coprono dettagli prima disponibili solo tramite parsing manuale.
Primitiva post-quantum: ML-KEM-768
Un'aggiunta piccola ma lungimirante: sgcKEM_CreateMLKEM768Keys genera una coppia di chiavi ML-KEM-768 (FIPS 203 / Kyber-768) sia in formato PEM sia in raw-bytes. ML-KEM è il KEM post-quantum standardizzato dal NIST e sulla roadmap IETF per il TLS 1.3 ibrido (X25519MLKEM768). Questo sblocca la sperimentazione di handshake PQ-ready in anticipo rispetto alla prossima baseline OpenSSL 3.5 / 3.6.
uses sgcKEM;
var vPubPEM, vPrivPEM: string; vPubRaw, vPrivRaw: TBytes;
begin
sgcKEM_CreateMLKEM768Keys(vPubPEM, vPrivPEM, vPubRaw, vPrivRaw);
TFile.WriteAllText('mlkem768_pub.pem', vPubPEM);
TFile.WriteAllText('mlkem768_priv.pem', vPrivPEM);
end;
Correzioni di affidabilità e conformità
Il batch di bug fix chiude un lungo elenco di problemi MCP, HTTP.sys, IOCP e HTTP/2. Punti salienti:
- MCP Server — credenziali mancanti o non valide ora restituiscono
401 Unauthorizedcon un headerWWW-Authenticate: Bearerche punta ai metadati della risorsa protetta, invece di500 Internal Server Error. Necessario per la discovery OAuth da parte dei client MCP basati su browser. - MCP Server — le richieste
OPTIONSnon raggiungono più il parser JSON-RPC (in precedenza restituivano500 "Invalid jsonrpc Value"). Il preflight CORS è ora gestito prima dell'autenticazione e prima del parser del body MCP. - MCP Server — descrizioni di tool, messaggi di prompt e contenuti di risorse contenenti caratteri non-ASCII non interrompono più la connessione (il body JSON ora corrisponde al
charset=utf-8dichiarato). - MCP Server — i campi
nameditool/prompt/resource/root/template/ completion-ref e completion-argument contenenti caratteri non-ASCII vengono ora correttamente emessi e letti come escape JSON\uXXXXanziché code point UTF-16 grezzi. - Body delle richieste HTTP API —
TsgcWSComponent_Server.DoHTTPRequestAPIchiamavaReadStringFromStreamsenza specificare una codifica, ricadendo su ASCII e sostituendo ogni byte non-ASCII con?prima che gli handler degli eventi lo vedessero. Risolto. - HTTP.sys Server — leak di contesto su
ERROR_MORE_DATAinTsgcHTTPServerAPI.DoExecute. Il ciclo di accept ora aumenta il buffer e ritentaHttpReceiveHttpRequestsullo stesso request id, e rilascia i contesti orfani su tutti i percorsi di errore. - HTTP.sys Server —
TsgcWSConnectionServer_HTTPAPI.DoSendHTTP_Responsenon imposta piùHTTP_SEND_RESPONSE_FLAG_MORE_DATAsulla risposta finale. - IOHandler IOCP —
TsgcIndy_IO_Engine_IOCP_Base.DoStopThreadschiamavaWaitForMultipleObjectssu un array di ID threadDWORD(FThreadsId) invece di HANDLE di thread. Risolto. - IOHandler IOCP — le operazioni di I/O pendenti sui socket sono ora annullate allo shutdown e alla chiusura per-socket.
- IOHandler IOCP — la fragile sonda
Overlapped.Internal = STATUS_PENDINGinDoFreePerIoDataè sostituita da un flag esplicitoCompleted: BooleansuTsgcPerIoData. - WebBrokerBridge HTTP/2 — Invalid pointer operation su
sgcFree(oResponse)inTsgcWSHTTPServer.OnHTTP2RequestEventquando DataSnap REST gestiva un frame HTTP/2 di soliHEADERS.
Aggiornamento
2026.5 è un aggiornamento drop-in per i progetti 2026.4 esistenti. Non sono state apportate modifiche alle interfacce dei componenti esistenti; i nuovi componenti rate-limit / circuit-breaker / API-key sono additivi e opt-in. La modalità ad alte prestazioni di HTTP.sys è gestita tramite FineTune.OperatingMode := ompHighPerf — il codice esistente resta sul percorso classico.
I clienti con una sottoscrizione attiva possono scaricare la nuova build dall'area clienti. Gli utenti in versione trial possono ottenere l'installer aggiornato su esegece.com/products/sgcwebsockets/sgcwebsockets-download.
Domande, feedback o aiuto per la migrazione? Contattaci — riceverai una risposta dalle persone che hanno scritto il codice.
