Every browser on the planet sends Accept-Encoding: gzip, deflate on every request. Until now, the sgcWebSockets HTTP servers ignored it and sent the body uncompressed. Your HTML, your CSS, your JavaScript and your JSON went out over the wire at full size, even though the client was telling you, on every single request, that it would happily unpack a smaller one.
sgcWebSockets 2026.7 adds response compression to the HTTP servers. When the client advertises gzip or deflate, the server can now compress the reply before sending it. It works for static files served from DocumentRoot and for replies you build yourself in an event handler. It is off by default, so upgrading changes nothing until you turn it on.
Turning it on
Compression is configured through a single options object, HTTPCompression, on the server. On TsgcWebSocketHTTPServer it is a published property, so you can set it in the Object Inspector at design time, or in code:
uses
sgcWebSocket;
begin
sgcWebSocketHTTPServer1.HTTPCompression.Enabled := True;
sgcWebSocketHTTPServer1.Active := True;
end;
That is the whole setup. With Enabled := True the server looks at the Accept-Encoding header of every request, and if the client supports one of the configured algorithms, it compresses the response body and sets Content-Encoding accordingly. It also adds Vary: Accept-Encoding, so caches and proxies in front of your server key on the encoding instead of handing a gzipped body to a client that cannot read it.
If the client does not advertise compression, nothing happens and the response goes out exactly as before. Compression is never forced on a client that did not ask for it.
The Algorithms property is a set, and both members are enabled by default:
sgcWebSocketHTTPServer1.HTTPCompression.Algorithms := [caGZip, caDeflate];
// or gzip only, if you prefer to keep it to a single well-understood encoding
sgcWebSocketHTTPServer1.HTTPCompression.Algorithms := [caGZip];
When the client supports both, the server prefers gzip.
What gets compressed, and what does not
Not every response is worth compressing. The ContentTypes list decides which ones are, and it ships with a sensible default: text/*, application/json, application/javascript, application/xml, application/xhtml+xml and image/svg+xml. Entries ending in /* match a whole family, so text/* covers HTML, CSS, plain text and the rest.
Text, HTML, CSS, JavaScript and JSON compress very well, because they are full of repeated tokens, tag names and whitespace. Already-compressed formats do not. A JPEG, a PNG, a WebP image, a ZIP archive, a .gz file or an MP4 video has already had its redundancy squeezed out, and running it through zlib again just burns CPU to produce a body of roughly the same size, sometimes a slightly larger one. Those content types are not in the list, so they are skipped.
You can replace the list with your own:
uses
sgcWebSocket, sgcWebSocket_Classes;
begin
with sgcWebSocketHTTPServer1.HTTPCompression do
begin
ContentTypes.Clear;
ContentTypes.Add('text/*'); // html, css, plain text
ContentTypes.Add('application/json'); // your API replies
ContentTypes.Add('application/javascript');
ContentTypes.Add('image/svg+xml');
ContentTypes.Add('application/x-ndjson'); // whatever else you serve
Enabled := True;
end;
sgcWebSocketHTTPServer1.Active := True;
end;
The check ignores any charset suffix, so a response with Content-Type: text/html; charset=utf-8 still matches text/*. There is also a belt-and-braces rule in the server: if the compressed body comes out no smaller than the original, the compression is discarded and the plain body is sent. You cannot end up shipping more bytes than you would have without it.
Compression level and minimum size
Level is the usual zlib level, 1 to 9, and it defaults to 6. That default is the standard speed against ratio compromise, and it is the value almost every web server in the world runs at. Raising it to 9 costs measurably more CPU on every single response, and for JSON it rarely buys you much extra: the big win over the uncompressed body happens at level 1 already, and levels 6 to 9 fight over the last few percent. If your server is CPU bound, moving down to 3 or 4 is a far more interesting experiment than moving up to 9.
MinSize defaults to 1024 bytes, and bodies smaller than that are sent as they are. A gzip stream carries its own header and trailer, and below a kilobyte or so the framing overhead plus the CPU cost is simply not worth the handful of bytes you save. Tiny JSON acknowledgements and short redirects fall into this bucket, and they should.
with sgcWebSocketHTTPServer1.HTTPCompression do
begin
Level := 6; // 1..9, default 6
MinSize := 1024; // bytes, default 1024, smaller bodies are sent as-is
Enabled := True;
end;
What it buys you
The gain shows up on the wire, not in your code. An HTML page or a JSON API reply is highly repetitive, so a typical payload of a few tens of kilobytes usually compresses several times over before it leaves the server. Fewer bytes on the wire means fewer round trips to get them there, and that is where it really pays: on mobile connections and on high-latency links, the time to deliver a response is dominated by the number of round trips, not by the bandwidth. A body that fits in fewer packets simply arrives sooner.
The cost is CPU on the server, once per response, and it is small at the default level. For a text-heavy site or a JSON API, the trade is almost always worth taking.
Replies you build yourself
You do not have to do anything special in your event handlers. Build the response the way you always have, set ContentText or ContentStream and the ContentType, and the server compresses it on the way out if the client asked for compression and the content type is in the list:
procedure TForm1.sgcWebSocketHTTPServer1CommandGet(aConnection: TsgcWSConnection;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
if ARequestInfo.Document = '/api/orders' then
begin
AResponseInfo.ContentType := 'application/json';
AResponseInfo.ContentText := GetOrdersAsJSON; // your payload, plain text
// nothing else to do. If the client sent Accept-Encoding: gzip and the
// body is at least MinSize bytes, it goes out gzipped.
end;
end;
The compression step runs after your handler returns, so the Content-Length the client sees is the compressed length, and Content-Encoding is set for you. If you set ContentEncoding yourself, because you are serving a body that is already compressed, the server leaves your response completely alone.
Two response kinds are deliberately never compressed: Server-Sent Events streams (text/event-stream), which must not be buffered, and bodyless responses such as 204 and 304.
Files served from DocumentRoot
Static files get the same treatment, with no code at all. Point the server at a folder, enable compression, and the HTML, CSS, JavaScript, SVG and JSON files under it are compressed on the way out. The images and the archives in the same folder are not, because their content types are not in the list.
sgcWebSocketHTTPServer1.HTTPUploadFiles.DocumentRoot := 'C:\www';
sgcWebSocketHTTPServer1.HTTPCompression.Enabled := True;
sgcWebSocketHTTPServer1.Active := True;
// GET /index.html -> compressed, text/html is in ContentTypes
// GET /app.js -> compressed
// GET /logo.png -> not compressed, image/png is not in the list
// GET /favicon.ico -> not compressed
The HTTP.sys server
The Windows HTTP.sys server, TsgcWebSocketServer_HTTPAPI, has the same HTTPCompression options object, with the same properties and the same defaults. There is one difference worth being precise about: on the HTTP.sys server the property is public rather than published, so it does not appear in the Object Inspector. You have to set it in code, before you activate the server:
uses
sgcWebSocket_Server_HTTPAPI;
begin
sgcWebSocketServer_HTTPAPI1.HTTPCompression.Enabled := True;
sgcWebSocketServer_HTTPAPI1.HTTPCompression.Level := 6;
sgcWebSocketServer_HTTPAPI1.HTTPCompression.MinSize := 1024;
sgcWebSocketServer_HTTPAPI1.Active := True;
end;
HTTP/1.1 only, for now
In this release, only HTTP/1.1 responses are compressed. HTTP/2 and HTTP/3 replies are not touched. If you are serving your site over HTTP/2, this feature does not change anything for you yet. It is worth being clear about that rather than letting you enable a property and wonder why nothing shrank.
Availability
HTTP response compression is available in sgcWebSockets 2026.7 for Delphi 7 through 13 and C++Builder, on Win32, Win64, Linux64 and macOS. It is off by default: nothing about your existing servers changes on upgrade until you set HTTPCompression.Enabled := True.
Customers with an active subscription can download the new build from the customer area. Trial users can grab the updated installer at esegece.com/products/websockets/download.
Questions, feedback or help tuning the content types for your own server? Get in touch, you will get a reply from the people who wrote the code.
