Repository navigation
Compression
Request and response bodies can be compressed with gzip using the HTTP-style Content-Encoding / Accept-Encoding headers. Compression is opt-in on both sides and transparent to handlers: received bodies are decompressed before your code sees them.
// Server: compress responses for clients that accept gzip
services.AddArgusPipeHost(options =>
{
options.PipeName = "my-pipe";
options.Compression.Enabled = true;
});
// Client: accept compressed responses and compress large request bodies
services.AddArgusClient("my-pipe", client => client.Compression.Enabled = true);Or on a client instance: client.Compression.Enabled = true;.
| Side | Behavior |
|---|---|
Client, Compression.Enabled
|
Adds Accept-Encoding: gzip to every request. Adds Content-Encoding: gzip and compresses the body when it is at least MinimumBodySize bytes. |
| Host, always | Decodes requests whose Content-Encoding is one of the configured encodings -- even when its own compression is disabled. An unknown encoding gets 400 Bad Request. |
Host, Compression.Enabled
|
Compresses a response body of at least MinimumBodySize bytes when the request's Accept-Encoding accepts a configured encoding. |
-
Accept-Encodingis parsed like HTTP:q=0excludes an encoding,*accepts any, and thePreferredEncodingwins when several are accepted. - Headers you set yourself are kept: setting
Content-Encoding: identityon a request prevents compressing it. - The client adds its headers only to what it sends: the
ArgusRequestyou pass toSendAsyncis not modified, so it can be inspected afterwards or reused with another client. - After decoding, the
Content-Encodingheader is removed from the message, soBody/BodyStreamand the headers describe the decoded content. - Streamed bodies (
BodyStream) are compressed on the fly in chunked transfer encoding, without buffering the whole body. A stream of unknown length is always compressed when compression applies.
Client compression assumes the server supports it. A server older than this feature would not decode compressed requests, so only enable client compression against an up-to-date host. Response compression is safe either way: the host only compresses when the client asked for it.
Available as ArgusClient.Compression and ArgusPipeHostOptions.Compression:
| Property | Type | Default | Description |
|---|---|---|---|
Enabled |
bool |
false |
Compress outgoing bodies (see the table above). Decoding is always on. |
MinimumBodySize |
int |
1024 |
Bodies smaller than this (in bytes) are sent uncompressed, because compressing them costs more than it saves. |
PreferredEncoding |
string |
"gzip" |
The encoding used to compress, when the other side accepts it. Must match one of Encodings. |
Encodings |
IList<IArgusContentEncoding> |
[ GZipArgusContentEncoding ] |
Supported encodings for decoding, the Accept-Encoding header and compressing. |
GZipArgusContentEncoding.CompressionLevel defaults to CompressionLevel.Fastest, which suits local IPC where CPU time matters more than the last few percent of size.
On the host, ArgusPipeHostOptions.MaxRequestBodySize limits both the compressed size on the wire and the decompressed size. A small request that inflates beyond the limit is rejected with 400 Bad Request ("Decompressed body size exceeds the maximum allowed size of N bytes"). Corrupt compressed data is also answered with 400.
Implement IArgusContentEncoding and add it to Encodings:
public class BrotliContentEncoding : IArgusContentEncoding
{
public string Name => "br";
public Stream CreateCompressionStream(Stream destination) =>
new BrotliStream(destination, CompressionLevel.Fastest, leaveOpen: true);
public Stream CreateDecompressionStream(Stream source) =>
new BrotliStream(source, CompressionMode.Decompress, leaveOpen: true);
}
options.Compression.Encodings.Add(new BrotliContentEncoding());
options.Compression.PreferredEncoding = "br";The returned streams must leave the inner stream open when disposed.
The wire serializers compress and decompress based on the Content-Encoding header, using their ContentEncodings property (gzip by default). This only works on the byte-safe Stream overloads (WriteAsync(Stream, …) / ReadAsync(Stream, …)). The text-based overloads (Write(message) returning a string, Read(string), the StreamReader readers and the synchronous StreamWriter writes) cannot carry compressed bytes and throw InvalidOperationException for a message with a Content-Encoding. See Serialization.
- Client Usage -- client configuration
- Server Configuration -- host options and body size limits
-
Wire Format Reference --
Content-EncodingandAccept-Encodingon the wire
copyright @ Sam Gerené