Tous les navigateurs de la planète envoient Accept-Encoding: gzip, deflate à chaque requête. Jusqu'à présent, les serveurs HTTP de sgcWebSockets l'ignoraient et envoyaient le corps de la réponse sans compression. Votre HTML, votre CSS, votre JavaScript et votre JSON partaient sur le réseau à taille pleine, alors que le client vous répétait, à chaque requête, qu'il aurait volontiers décompressé une version plus petite.
sgcWebSockets 2026.7 ajoute la compression des réponses aux serveurs HTTP. Lorsque le client annonce gzip ou deflate, le serveur peut désormais compresser la réponse avant de l'envoyer. Cela fonctionne pour les fichiers statiques servis depuis DocumentRoot et pour les réponses que vous construisez vous-même dans un gestionnaire d'événement. La fonctionnalité est désactivée par défaut, donc la mise à jour ne change rien tant que vous ne l'activez pas.
Activer la compression
La compression se configure via un unique objet d'options, HTTPCompression, sur le serveur. Sur TsgcWebSocketHTTPServer, c'est une propriété publiée, vous pouvez donc la régler dans l'inspecteur d'objets à la conception, ou par code :
uses
sgcWebSocket;
begin
sgcWebSocketHTTPServer1.HTTPCompression.Enabled := True;
sgcWebSocketHTTPServer1.Active := True;
end;
C'est toute la configuration. Avec Enabled := True, le serveur examine l'en-tête Accept-Encoding de chaque requête et, si le client prend en charge l'un des algorithmes configurés, il compresse le corps de la réponse et positionne Content-Encoding en conséquence. Il ajoute également Vary: Accept-Encoding, afin que les caches et les proxys placés devant votre serveur prennent l'encodage en compte au lieu de servir un corps compressé en gzip à un client incapable de le lire.
Si le client n'annonce pas la compression, rien ne se passe et la réponse part exactement comme avant. La compression n'est jamais imposée à un client qui ne l'a pas demandée.
La propriété Algorithms est un ensemble, et ses deux membres sont activés par défaut :
sgcWebSocketHTTPServer1.HTTPCompression.Algorithms := [caGZip, caDeflate];
// or gzip only, if you prefer to keep it to a single well-understood encoding
sgcWebSocketHTTPServer1.HTTPCompression.Algorithms := [caGZip];
Lorsque le client prend en charge les deux, le serveur préfère gzip.
Ce qui est compressé, et ce qui ne l'est pas
Toutes les réponses ne méritent pas d'être compressées. La liste ContentTypes décide lesquelles le sont, et elle arrive avec une valeur par défaut raisonnable : text/*, application/json, application/javascript, application/xml, application/xhtml+xml et image/svg+xml. Les entrées se terminant par /* correspondent à toute une famille, ainsi text/* couvre le HTML, le CSS, le texte brut et le reste.
Le texte, le HTML, le CSS, le JavaScript et le JSON se compressent très bien, car ils sont pleins de motifs répétés, de noms de balises et d'espaces. Les formats déjà compressés, non. Une image JPEG, PNG ou WebP, une archive ZIP, un fichier .gz ou une vidéo MP4 ont déjà eu leur redondance éliminée, et les repasser dans zlib ne fait que consommer du processeur pour produire un corps de taille à peu près identique, parfois légèrement plus grand. Ces types de contenu ne figurent pas dans la liste, ils sont donc ignorés.
Vous pouvez remplacer la liste par la vôtre :
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;
La vérification ignore tout suffixe de jeu de caractères, ainsi une réponse avec Content-Type: text/html; charset=utf-8 correspond toujours à text/*. Il existe aussi une règle de sécurité supplémentaire dans le serveur : si le corps compressé n'est pas plus petit que l'original, la compression est abandonnée et le corps brut est envoyé. Vous ne pouvez pas finir par expédier plus d'octets que vous n'en auriez envoyés sans elle.
Niveau de compression et taille minimale
Level est le niveau zlib habituel, de 1 à 9, avec 6 par défaut. Cette valeur par défaut est le compromis classique entre vitesse et taux, et c'est celle qu'utilise pratiquement tous les serveurs web du monde. La porter à 9 coûte sensiblement plus de processeur sur chaque réponse et, pour du JSON, cela apporte rarement grand-chose : le gros du gain par rapport au corps non compressé est déjà obtenu au niveau 1, et les niveaux 6 à 9 se disputent les derniers pourcents. Si votre serveur est limité par le processeur, descendre à 3 ou 4 est une expérience bien plus intéressante que de monter à 9.
MinSize vaut 1024 octets par défaut, et les corps plus petits sont envoyés tels quels. Un flux gzip transporte son propre en-tête et sa propre queue, et en dessous d'un kilooctet environ, le surcoût de l'encadrement plus le coût processeur ne valent tout simplement pas la poignée d'octets économisés. Les petits accusés de réception JSON et les courtes redirections tombent dans cette catégorie, et c'est très bien ainsi.
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;
Ce que cela vous apporte
Le gain apparaît sur le réseau, pas dans votre code. Une page HTML ou une réponse d'API JSON est très répétitive, donc une charge utile typique de quelques dizaines de kilooctets se compresse généralement plusieurs fois avant de quitter le serveur. Moins d'octets sur le réseau, cela veut dire moins d'allers-retours pour les acheminer, et c'est là que le bénéfice est réel : sur les connexions mobiles et sur les liens à forte latence, le temps de livraison d'une réponse est dominé par le nombre d'allers-retours, pas par la bande passante. Un corps qui tient dans moins de paquets arrive tout simplement plus tôt.
Le coût, c'est du processeur sur le serveur, une fois par réponse, et il est faible au niveau par défaut. Pour un site riche en texte ou une API JSON, l'échange vaut presque toujours la peine.
Les réponses que vous construisez vous-même
Vous n'avez rien de particulier à faire dans vos gestionnaires d'événements. Construisez la réponse comme vous l'avez toujours fait, renseignez ContentText ou ContentStream ainsi que le ContentType, et le serveur la compresse à la sortie si le client a demandé la compression et si le type de contenu figure dans la liste :
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;
L'étape de compression s'exécute après le retour de votre gestionnaire, donc le Content-Length que voit le client est la longueur compressée, et Content-Encoding est renseigné pour vous. Si vous renseignez vous-même ContentEncoding, parce que vous servez un corps déjà compressé, le serveur laisse votre réponse totalement intacte.
Deux types de réponses ne sont délibérément jamais compressés : les flux Server-Sent Events (text/event-stream), qui ne doivent pas être mis en tampon, et les réponses sans corps comme 204 et 304.
Les fichiers servis depuis DocumentRoot
Les fichiers statiques reçoivent le même traitement, sans une ligne de code. Pointez le serveur vers un dossier, activez la compression, et les fichiers HTML, CSS, JavaScript, SVG et JSON qui s'y trouvent sont compressés à la sortie. Les images et les archives du même dossier ne le sont pas, car leurs types de contenu ne figurent pas dans la liste.
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
Le serveur HTTP.sys
Le serveur HTTP.sys de Windows, TsgcWebSocketServer_HTTPAPI, dispose du même objet d'options HTTPCompression, avec les mêmes propriétés et les mêmes valeurs par défaut. Il y a une différence qu'il vaut la peine de préciser : sur le serveur HTTP.sys, la propriété est publique et non publiée, elle n'apparaît donc pas dans l'inspecteur d'objets. Vous devez la régler par code, avant d'activer le serveur :
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 seulement, pour l'instant
Dans cette version, seules les réponses HTTP/1.1 sont compressées. Les réponses HTTP/2 et HTTP/3 ne sont pas touchées. Si vous servez votre site en HTTP/2, cette fonctionnalité ne change encore rien pour vous. Il vaut mieux le dire clairement que de vous laisser activer une propriété en vous demandant pourquoi rien n'a rétréci.
Disponibilité
La compression des réponses HTTP est disponible dans sgcWebSockets 2026.7 pour Delphi 7 à 13 et C++Builder, sur Win32, Win64, Linux64 et macOS. Elle est désactivée par défaut : rien ne change dans vos serveurs existants lors de la mise à jour tant que vous n'avez pas défini HTTPCompression.Enabled := True.
Les clients disposant d'un abonnement actif peuvent télécharger la nouvelle version depuis l'espace client. Les utilisateurs en version d'essai peuvent récupérer le programme d'installation mis à jour sur esegece.com/products/websockets/download.
Des questions, des remarques ou besoin d'aide pour ajuster les types de contenu de votre propre serveur ? Contactez-nous, vous recevrez une réponse des personnes qui ont écrit le code.
