sgcWebSockets 2026.9.0 Latest
- 2026.9.0: 2026 September
- NewNew sgcWebRTC package: a native WebRTC media engine for Delphi and C++ Builder, TsgcRTCPeerConnection, with audio and video calls, screen sharing and SCTP data channels. It runs as pure code, with no browser or WebView control, on Windows, Linux, macOS, iOS and Android.
- NewNew sgcCrypto package: AES and ChaCha20/XChaCha20-Poly1305 AEAD, SHA-2/SHA-3, Argon2, scrypt, HKDF, Ed25519, Ed448, X25519, X448, secp256k1, RSA key generation, X.509 certificate and CSR generation, and the post-quantum ML-KEM, ML-DSA and SLH-DSA algorithms.
- NewNew sgcHTML components: CameraScanner, a live camera panel that reads barcodes and QR codes with the browser's own built in scanner and always offers a manual entry fallback, NumPad, CommandPalette and EmptyState.
- NewNew sgcHTML demos, five complete applications with sign in, a database and printable reports, under Demos\60.HTML\01.RunTime: warehouse management (13.Warehouse), point of sale (14.POS), reporting portal (15.Reports), multi tenant SaaS control plane (16.SaaS) and field service dispatch (17.FieldService).
- NewNew "Runtime vs Design-Time" help topic and demos, showing how to build sgcHTML pages by dropping the same components on a VCL form instead of composing them in code.
- NewNew ExportFolder property on the sgcHTML design host, where the designed page is written when the export route runs. It is empty by default, and while it is empty an export writes nothing.
- NewNew PartialRequestTimeout option on the EPOLL and IOCP IOHandlerOptions, off by default. An HTTP request body that does not all arrive within a single readiness event or completion, for example a large POST split across packets, used to be dropped with the connection closed and no reply. The server now waits for the rest of it, on a separate thread pool so a slow client cannot hold up the others.
- NewNew ForwardedHeaders property on TsgcWebSocketFirewall, off by default, which recovers the real client address when the server sits behind a reverse proxy. The address carried in X-Forwarded-For or X-Real-IP is only believed when the connection itself arrives from an address listed in TrustedProxies, so a client cannot invent one, and the chain is read from the right, past the number of proxies given in TrustedHops, because the leftmost entry is the one the client supplied. Once resolved it replaces the connection IP, so the blacklist, the whitelist, GeoIP, the custom rules, the events and your own handler code all see the end client instead of the proxy, and the original socket address stays available as PeerIP. Resolution runs on every request, because a proxy reuses one connection for requests from different clients. RateLimit.MaxConnectionsPerIP still counts the sockets opened by the proxy, since it measures connections rather than callers. The settings behave the same way on the http.sys server as on the Indy one.
- NewNew Kraken WebSocket v2 API component, TsgcWSAPI_Kraken_V2, alongside the existing v1 one. It implements the method/params/req_id protocol across the six public channels, the executions and balances private channels, and the add, amend, edit, cancel, cancel all, cancel all after, batch add and batch cancel verbs, with its own events. The v1 component is unchanged.
- NewThe Huobi WebSocket API component now opens a second connection internally when an ApiKey is configured, so one component instance serves public market data and private account data at the same time. The public API is unchanged.
- NewNew UseServerTimeOffset option on the Binance REST and WebSocket clients, off by default. REST_API.SyncServerTime measures the difference between the exchange clock and the local one and applies it to every signed request from then on, so a client whose clock has drifted no longer has its private requests rejected.
- NewNew Throttle.PaceBatch option on the WebSocket API clients, True by default. A subscription which carries more streams than fit in one frame is split into several, and that burst is now paced like any other, so a single call with hundreds of streams no longer trips the message rate limit of the exchange.
- NewNew Throttle.AsyncResubscribe option on the WebSocket API clients, True by default. The paced replay after a reconnect now runs on a background worker, so the connect notification returns straight away instead of waiting for the whole watchlist to be sent.
- NewThe Deribit WebSocket client now reads expires_in and refresh_token from the authentication reply and refreshes the authorisation before it expires, so a long lived session no longer loses it silently.
- NewNew AllowUnsignedWebhooks option on the Cryptohopper client, False by default. The webhook signature is now always verified, and this option is the explicit way to accept an unsigned payload when no ClientSecret is configured.
- NewNew overloads of NewMarketOrder and NewLimitOrder on the Cex Plus WebSocket client which take the amount of the order.
- NewImproved OpenAPI Server: the request validation now also checks the header and the cookie parameters, with the new ValidateHeaderParams, ValidateCookieParams and EnforceRequired options, and the schema keywords the validator does not implement are reported when the specification is loaded, through the new Validation.Warnings property.
- NewImproved OpenAPI Client: added support for cookie parameters and for the complete OpenAPI parameter serialization rules, matrix, label, simple, form, spaceDelimited, pipeDelimited and deepObject, with explode and allowReserved. New AddArray and AddObject methods.
- NewImproved JWT Server: new Validations.Leeway option, the clock skew allowed when the exp, nbf and iat claims are checked. It defaults to 60 seconds.
- NewThe QUIC and HTTP/3 client and server now support IPv6. An address that carries a colon, such as ::1, is treated as an IPv6 address, and a URL can carry it in brackets, https://[::1]:443/. A host name is now resolved over both families, where before only IPv4 was tried, so a name published with AAAA records only can now be reached. The HTTP/3 listener with no Host set serves both families through a single socket.
- NewNew Host property on HTTP3Options, the address the HTTP/3 listener binds. It is empty by default, which binds every interface, and it takes an IPv4 address, an IPv6 address or a host name. Use it when the HTTP/3 listener has to stay on one interface, because that listener owns a single socket and does not read Bindings.
- NewNew OnQueueDrained event on the WebSocket client, server and HTTP server, raised when the outgoing queue of a connection goes from holding messages to being empty. It is raised on the connection thread, right after the queue is drained and before the next read, so a relay can hand out the next credit without waiting. Because it is not marshalled through NotifyEvents, the handler must not touch the user interface.
- NewNew PendingCount property on TsgcWSConnection, the number of messages still queued for that connection, summed across the three priority levels. It returns 0 when nothing is queued and reading it allocates nothing, so it can be polled to run a credit window instead of a stop and wait exchange.
- NewNew exports on the library, sgcWSClient_Connection_PendingCount, sgcWSServer_Connection_PendingCount, sgcWSClient_OnQueueDrained and sgcWSServer_OnQueueDrained, which carry the new PendingCount property and OnQueueDrained event across to the .NET wrapper and to any other host that consumes sgcWebSockets.dll. They are appended, so the existing export order is unchanged.
- NewNew Revocation options on the SChannel settings of the servers, SSLOptions.SChannel_Options.Revocation, so a server that asks its clients for a certificate can also check whether that certificate has been revoked. The client side already had them. Check selects how much of the client chain is looked up (off by default), Timeout bounds the whole CRL and OCSP lookup so an unreachable responder cannot hold up the handshake (5 seconds by default), CacheOnly uses only what Windows has already cached and never goes to the network (off by default), and IgnoreRevocationOffline and IgnoreNoRevocationCheck decide whether a client is still let in when the responder cannot be reached or when its certificate publishes no revocation information (both on by default). A certificate confirmed revoked is always refused. Setting Preset to tlspSecureDefaults now turns the check on for the server too, as it already did for the client.
- FixedFixed access violations on the WebSocket server when Server.WriteData or Broadcast, including a Broadcast to a channel, used a connection while it was being freed on another thread.
- FixedFixed access violations when a WebSocket component or one of its API components was freed while still connected, or while the WatchDog, HeartBeat, reconnect replay or Throttle threads were running. Those threads are now stopped, and the API detached from its client, before any destructor releases what they read. Two heartbeat timer threads also leaked for every component destroyed.
- FixedFixed HTTP requests bigger than about 1 MB being dropped with no reply at all when the client did not send an Expect: 100-continue header. The request body was pulled into the header buffer, which then passed its size limit and the connection was closed.
- FixedFixed server connections never being released on the EPOLL engine once the client closed, on both plain and SSL connections. The connection stayed in the server list, OnDisconnect never fired and every Broadcast kept writing to it.
- FixedFixed the EPOLL engine closing a connection whenever a single socket read filled the receive buffer, so any HTTP request or WebSocket message larger than about 32 KB lost its data and was dropped with no reply. The socket is now drained into a buffer that grows as it needs to.
- FixedFixed the EPOLL and IOCP engines dropping any request that did not arrive in a single socket read, and closing SSL connections when a TLS record arrived split across two TCP segments. Both are what happens at any MTU boundary, over a VPN, or whenever a client flushes the headers and the body separately. The engines now wait for the rest instead of giving up.
- FixedFixed SSL responses being silently truncated on the EPOLL and IOCP engines when the client was slow to read, because the count of bytes the send call actually took was ignored. Two error checks on that path also used the numeric Windows socket error values, so on Linux neither a full send buffer nor a connection reset by the peer was recognised.
- FixedFixed an access violation on the EPOLL and IOCP engines when a connection's HeartBeat timeout was detected while a WorkOpThreads worker was still handling that connection.
- FixedFixed the sgc protocol server keeping a QoS level 2 message after the connection which published it had gone, so any other client could release it by naming its id and replay the publish under the original client's identity. Pending level 2 messages are now discarded when that connection closes. The QoS retry timer on the server and the client also walked the pending list with no lock while connection threads changed it.
- FixedFixed the Presence server registering a member under the id sent by the client instead of the session id, so an entry under any other id was never removed when the connection closed and the next broadcast wrote through the freed connection. It also destroyed a roster owned member when the application refused a join through OnBeforeNewChannelMember, leaving a dangling pointer.
- FixedFixed the Kafka decoder bounds check being defeated by an integer overflow, so a length near 2 GB passed the guard and the read went outside the frame buffer, and Skip was unchecked and could drive the offset negative. The arithmetic is now done in Int64, a negative offset is rejected and Skip is bounds checked.
- FixedFixed the AMQP 1.0 decoder casting a wire selected class to a described list without checking it. Six descriptor codes, among them data, amqp-value and application-properties, resolve to sibling classes rather than descendants, so a virtual method was dispatched through a slot the real class does not have. An unregistered descriptor also called Create on a nil class reference.
- FixedFixed the HTTP/2 path serving DocumentRoot files and forwarding requests before the Basic authentication gate had run, so a request carrying no credentials at all was answered with the protected file while the same request over HTTP/1.1 was correctly refused.
- FixedFixed the OnBeforeCommand event not being taken into account on HTTP/2 and HTTP/3 requests, so an endpoint you had marked as public there, a login page for example, was still refused with the browser asking for a user and a password, while the very same endpoint over HTTP/1.1 was served correctly.
- FixedFixed the options of the OnBeforeCommand event behaving differently on HTTP/2, where authorizing one authentication scheme also skipped the checks of the others. They now behave the same on every connection.
- FixedFixed HTTP/3 requests following their own separate path instead of the one HTTP/1.1 requests follow, so the OpenAPI, MCP and REST API servers, the request forwarding, and the CORS, multi tenancy and metrics options never answered over HTTP/3. They all work over it now. The connection parameter of OnBeforeCommand, OnCommandGet and OnCommandOther is empty on HTTP/3, because an HTTP/3 request has no connection behind it.
- FixedFixed the DLL server holding every callback result, including the authentication verdict, in a single unlocked field shared by all connections, so with two connections authenticating at the same time one verdict was read back by the other and wrong credentials were admitted. Credentials, approved upload filenames and forward settings crossed the same way. The HTTP API server and the Files protocol in the DLL are fixed too.
- FixedFixed NewGuid being built from CreateGuid, which on Linux, macOS and iOS is a version 1 UUID made of the network card address and a timestamp, so only the low bits of the clock varied. It backs bearer tokens, OAuth client secrets, session ids and the watchdog secret, and those were predictable to anyone who had seen a single one of them. It now draws from the platform secure random source.
- FixedFixed the sgcHTML designer listener binding every interface instead of loopback, so the whole network could reach the unauthenticated designer routes on a developer machine, and its export route writing files into any directory named in the query string. It now binds 127.0.0.1 only and exports to the new ExportFolder property.
- FixedFixed the InputGroup component writing its type, name, value and placeholder attributes without escaping them, so a value containing a quote or an angle bracket could break out of the attribute and inject markup.
- FixedFixed the OpenAI Realtime client sending the configured Azure API key to api.openai.com. With the Azure provider selected the default conversation method returned the OpenAI endpoint, so the key went to the wrong vendor and the Azure session could never be established. Assigning the options also dropped the provider and the Azure settings.
- FixedFixed the JSON parser mishandling an array beginning with a line break, a value re-added with a different type, a string that looked like an array, and number formatting depending on the system locale. A floating point value that is not a real number was written out as NAN or INF, which no JSON parser can read, and is now written as null.
- FixedFixed credential headers surviving a redirect to another host and an HTTPS to HTTP downgrade in the ready made API clients. The protections existed but were left off, enforced nothing on the Standard and Professional editions, and the cross origin strip cleared only the raw headers. They are now on by default.
- FixedFixed the HTTP client repeating a request that should not be repeated. With retries switched on, a POST that the server had already carried out, and then dropped the connection on, was sent a second time, which could place a second order. Only GET, HEAD and OPTIONS are retried now, and a new Methods property in the retry options lets you allow others.
- FixedFixed retries not counting towards the request limit, so a single call could send more requests than the limit allows, one more for every retry. A retry now takes a slot just like the first attempt, and when the limit is set to reject it is turned down instead of going out.
- FixedFixed the response size limit (MaxResponseSize) measuring the compressed size of a reply instead of its size once unpacked, so a small compressed body that expanded into a very large one was accepted. This only affected builds using the Indy that comes with the IDE, the eSeGeCe Indy already checked it.
- FixedFixed Abort leaving most requests running. Only three of the eight ways a request is sent registered themselves, so Abort did nothing for the other five, and with more than one request in flight it could only reach the last one that started. It now stops every request that is running.
- FixedFixed private subscriptions (orders, balances, fills) never being replayed after a reconnect on Bitstamp, Coinbase, Deribit, Huobi, Kraken spot and futures, Kucoin, MEXC and ThreeCommas, so the reconnect looked successful while those feeds were silently gone.
- FixedFixed the reconnect replay running before authentication on BitMEX, Bitfinex, Crypto.com, Deribit and Kraken futures, so subscriptions were issued on a session the exchange had not yet authenticated.
- FixedFixed money being rounded before it was signed across the exchange REST and WebSocket clients, which could turn a very small size such as 0.000000004 into zero, quantise a value to ten decimals, send prices in scientific notation or cap them at fifteen significant digits. Every client now shares one formatter, which emits the shortest decimal that reads back as the very same value. The formatter has also been corrected at its edges: a very small amount was returned as 0, a very large one lost its decimals, and both ends could still come out in scientific notation. An amount that is not a real number, such as the result of a division by zero in the application, was sent as the text NAN, and is now reported as an error before anything is signed.
- FixedFixed HTX and Huobi building their signature timestamp from the local date and the UTC time, so on a host outside UTC every private request could fail for part of the day.
- FixedFixed every private request on the Kraken futures REST client (send, edit, cancel order, transfer, withdrawal) being sent as a GET with the body discarded, so none of them worked, and TsgcHTTPKrakenFutures_Options.Assign calling itself and raising a stack overflow.
- FixedFixed the Kraken spot WebSocket client connecting to the v2 endpoint while speaking the v1 protocol, so no subscription or status event ever fired. It now connects to v1 by default.
- FixedFixed the Binance WebSocket client re-subscribing an already unsubscribed kline, mark price, index price or all market mark price stream on every reconnect, and not splitting a large subscribe or unsubscribe call into batches, so a call over the exchange's stream count or frame size limit could be rejected while the client still believed it had succeeded.
- FixedFixed OKX trading operation failures, such as a rejected order, never reaching OnOKXError.
- FixedFixed every MEXC protobuf decoder raising an error on the first binary frame, so the protobuf market data path could not deliver a single message.
- FixedFixed the Cryptohopper webhook accepting any payload as authentic when no ClientSecret was configured, which is the default, and its signature check failing on a host whose code page is not UTF-8.
- FixedFixed a range of further signing, timestamp and request defects across Binance, Bitfinex, Bitstamp, Bitget, BitMEX, Coinbase, Cryptorobotics, Deribit, GateIO, Huobi, Kucoin, MEXC and OKX, among them BitMEX AmendOrder sent with no authentication headers at all, five Binance REST methods that could not work, and six Kucoin request construction defects.
- FixedFixed JWT Server: the exp, nbf and iat claims were never validated, only the signature was, so a correctly signed token whose expiration had passed was accepted indefinitely and the Validations.Expiration option had no effect. Setting it to False still disables the check.
- FixedFixed OpenAPI Server: a request body whose media type was not declared in the specification was validated as JSON anyway and one with no Content-Type at all was assumed to be JSON, both now answer 415, and a property declared readOnly is no longer accepted in a request body.
- FixedFixed OpenAPI Server: a deeply nested JSON body could exhaust the stack of the connection thread and crash the server, because the check that runs before the parser had no depth limit.
- FixedFixed OpenAPI Server: a regular expression that could not be compiled was ignored and the value treated as valid, and it was rebuilt on every request. Expressions are now cached, a value longer than 4096 characters is reported instead of being matched, and an invalid expression is reported as an error in the specification. On Delphi 7 to 2010 the pattern keyword cannot be enforced at all, which is now reported when the specification is loaded.
- FixedFixed OpenAPI Client: the generated clients did not verify the certificate of the server while sending tokens and api keys, a value passed to a header parameter was written unchecked so a carriage return or line feed could add headers of its own, and an encoded slash in a path parameter was turned back into a real one, so a value such as ../../admin was sent as a path traversal.
- FixedFixed OpenAPI Client: a multipart/form-data request was sent without the boundary in the header and carried only its first part, a PATCH carried no body at all, and a generated method for an OPTIONS, HEAD or TRACE operation sent nothing and returned an empty string with no error.
- FixedFixed OpenAPI Client: an optional parameter could not send limit=0, an empty string or a boolean set to False, an optional floating point parameter was always sent as 0, a base URL that already contained a query string produced a second question mark, and the OAuth2 token was refreshed while still valid and never once it had expired.
- FixedFixed OpenAPI Client: a response released a stream supplied by the caller, the routine that releases the objects of a class destroyed any object typed property and could free the same object twice, and an array of strings was written by reading object pointers as strings.
- FixedFixed the HTTP/3 server refusing to start when the private key was protected by a password, reported as "HTTP/3 Server: encrypted private keys are not supported". The HTTP/3 listener now reads SSLOptions.Password just like the HTTPS one, so a single key file serves both. An encrypted key with no password set used to leave the server waiting forever on a prompt nobody could see, and now fails with a clear message instead.
- FixedFixed ConnectTimeout being ignored on the QUIC and HTTP/3 clients. An unreachable server always took about 30 seconds whatever the property said, because the handshake was left to the SSL library and to its own budget. The configured value is now honoured, and it is 10 seconds by default.
- FixedFixed the QUIC client never returning from WriteData and from Disconnect. Every write waited for an answer the peer was under no obligation to send, and the disconnect went through that same wait, so a program that connected and then closed never came back. A second write from another thread queued behind the first. Disconnect also reported failure even when it had worked.
- FixedFixed the HTTP/3 client accepting any certificate while VerifyCertificate was True. The result of the check was worked out correctly and then discarded, so a certificate from an authority that is not trusted, or one issued to another host, was let through. The QUIC client was not affected.
- FixedFixed the WebSocket client never raising OnDisconnect when the server closed one connection with Connection.Disconnect over TLS. The TLS handler is already closed by then, and the layer underneath only raises its disconnect notifications while it is still open, so nothing was reported and the read thread had already been stopped. The client was left reporting Active, holding a connection that no longer existed, and a later shutdown of the whole server could not recover it. The WatchDog never reconnected either, because it starts from that notification.
- FixedFixed the connection teardown being skipped whenever the connection was already flagged as disconnected. Any code that correctly reported the peer as gone, including a write that failed with socket error 10052 to 10054, thereby cancelled the cleanup that closes the socket and raises OnDisconnect.
- FixedFixed writes continuing to be attempted on a connection that had already been torn down, which reported one error per write for as long as the application kept writing.
- FixedFixed OnError and OnException skipping the connection teardown when the application event handler raised an exception of its own.
- FixedFixed TsgcWebSocketServer_HTTPAPI silently discarding queued messages. The component accepted a QueueOptions level and copied it to every connection, but nothing on the http.sys engine ever drained the queue, so a message written to a connection was never sent and no error was reported. The engine is driven by IOCP completions and has no per connection loop to drain from, the same reason iohIOCP and iohEPOLL cannot. The queue is now switched off as the server starts, the three levels are reset to qmNone and the OnError event reports it, so messages are written inline instead of being lost. A level assigned after the server is already listening is reset the same way on every new connection.
- FixedFixed the MQTT client sending a publish without its properties, or with the properties of another message, when two or more threads published at the same time. The subscriber saw ResponseTopic and CorrelationData arrive empty, or belonging to a different message. Subscribe and UnSubscribe had the same problem with their own properties. A lock of your own around Publish is no longer needed.
- BreakingRemoved support for the AppRTC protocol and the RTCMultiConnection API. The TsgcWSPServer_AppRTC and TsgcWSAPIServer_RTCMultiConnection components, their units and their demos have been deleted. Use TsgcRTCPeerConnection or the WebRTC protocol server instead.
- BreakingRemoved support for the Flash fallback, which reached end of life in 2020. The FallBack.Flash options and published property, the Flash policy handler, the trpFlash transport and the WebSocketMain.swf and sgcWebSocketsFlash.js resources have all been deleted. Remove the FallBack.Flash lines from any .dfm that carries them, otherwise the form raises a property does not exist error, and the ordinal of every TwsTransport member after trpFlash has shifted by one.
- BreakingWorkOpThreads on the EPOLL and IOCP IOHandler options no longer keeps a connection on the same thread, because a connection waiting for the rest of a request held up every other connection on that thread. Anything kept per thread, such as a database connection or a thread local cache, can no longer be assumed to follow a connection. WorkOpThreads now sets the smallest number of workers kept ready and the pool grows from there. The WorkOpRoundRobin property is gone, remove it from your code and from any .dfm that carries it.
- BreakingTLSOptions.VerifyCertificate now binds the certificate to the host being connected to on the OpenSSL backend, as it already did on SChannel and Apple, so a chain valid certificate issued for a different host is rejected. A deployment which connected to a name its certificate does not carry will start failing. Connecting to a bare IP address still binds nothing, set OpenSSL_Options.X509Checks.Mode to include oslx509chIPAddress for that case.
- BreakingThe HTTP/3 listener now refuses a request it cannot authenticate instead of serving it. A server configured with OAuth2, JWT or WebAuthn answers 401 on HTTP/3, because those schemes need TCP connection state an HTTP/3 request does not have. Basic authentication is unaffected and is still enforced.
- BreakingWriteTimeout on the client components now defaults to 60 seconds instead of no limit at all, and it is applied on Linux, macOS, iOS and Android as well, where before it only ever took effect on Windows. A form saved before this change streams in a zero, which is read as unset and also gets the 60 second default. Set the property to a negative value to never time out.
- BreakingOn the Standard and Professional editions, setting MaxChunkSize, UseExpect100Continue or UseChunkedTransferEncoding to a non-default value now raises an exception. These three cannot be implemented on the Indy that ships with Delphi, and until now they did nothing without saying so. At their default values they still do nothing.
- BreakingStripAuthOnCrossHostRedirect and NoInsecureRedirect now default to True on the ready made API clients.
- BreakingThe Cryptohopper webhook now rejects a payload when no ClientSecret is configured. Set AllowUnsignedWebhooks to True for the previous behaviour.
- BreakingThe Kraken spot WebSocket client now connects to v1 by default instead of v2. See the corresponding fix above.
- BreakingThe MEXC futures PlaceOrder and SetPositionLeverage methods changed their parameters to match the contract API which MEXC publishes, so code which calls them needs updating. PlaceOrder takes openType where it took positionSide, and SetPositionLeverage takes positionId, openType and positionType where it took marginMode. The TestNet property is gone as well, MEXC has retired its futures testnet, the spot TestNet is unaffected.
- BreakingBinance PlaceLimitMakerOrder now takes a price, which is required because the order is rejected without it, and the fromId, orderListId and fromAllocationId parameters are now Int64 instead of Integer.
- BreakingType changes on the exchange clients: the Kucoin VisibleSize property and the Kraken WebSocket order price and volume properties are now strings, and the Cex order amount and price parameters are now Double.
- BreakingOpenAPI Client: the generated clients now verify the certificate of the server, set TLSOptions.VerifyCertificate to False for a self signed endpoint. The request body is now UTF-8 and an empty string serializes as "field": "", set JSONIgnoreEmptyStrings to True for the previous output. A response no longer frees a ResponseStream supplied by the caller, set OwnsResponseStream to True, and freeing the client from inside its own OnResponse, OnError or OnCancel handler now raises instead of hanging.
- BreakingOpenAPI Server: the request validation now also checks the header and the cookie parameters, so a specification declaring a required header that used to pass will now answer 400, and an undeclared media type now answers 415. TsgcOpenAPIValidation_Options has new published properties, so a form saved with this version will not load in an older one, and TsgcOpenAPIJSONValidator.Validate takes two more parameters.
- BreakingThe HTTP/3 client now really verifies the server certificate. TLSOptions.VerifyCertificate is True by default on TsgcHTTP3Client, but the result of the check was worked out and then thrown away, so every HTTP/3 client accepted any certificate, from any authority and issued to any host. The check is applied now. An HTTP/3 client that talks to a server with a self signed certificate, with a private authority that is not in the machine store, or with a certificate that does not name the host, stops connecting until the trust store or the certificate is put right. On TsgcQUICClient verification stays off by default, so nothing changes there unless you turn it on.
- BreakingVerifyCertificate on the QUIC and HTTP/3 clients now also binds the certificate to the host being connected to, as it already did on the TLS transports, so a certificate that is chain valid but issued for another name is rejected. A bare IP address is matched against the IP entries of the certificate, which most certificates do not carry.
- BreakingRemoved IdleTimeout from the QUIC server options. No part of the server ever read it, so it never did anything. Remove it from any .dfm that carries it, otherwise the form raises a property does not exist error.
- BreakingDTLSOptions.VerifyCertificate now enforces the result of the certificate check. Until now the result was worked out and then thrown away, so with verification switched on a certificate from any authority, or one issued to another host, was accepted. Verification is off by default, and WebRTC is unaffected because it authenticates the other end by the fingerprint carried in the SDP.
- BreakingDTLSOptions.RootCertFile is now the trust store used to verify the other end, which is what the same property already means on the TLS and QUIC transports. Before, it was loaded as this endpoint's own certificate. Put your own certificate in CertFile, which now reads a file holding the certificate together with its intermediates. A configuration that named a certificate in RootCertFile and a key in KeyFile while leaving CertFile empty is reported as an error when the component starts, so it cannot silently fall back to a generated certificate.
- BreakingWith retries switched on, only GET, HEAD and OPTIONS are retried by default. If you were relying on a POST being retried, add it to RetryOptions.Methods. The ready made AI clients set this themselves, so their requests keep retrying as before.
- BreakingA request stopped with Abort now raises EsgcHTTPAbort instead of an ordinary connection error, so you can tell your own abort apart from a connection that failed on its own.