Skip to content

Compression

The compression concern compresses content sent to the clients, if applicable. By default, gzip, Brotli and Zstandard (on .NET 11) are supported.

var content = Layout.Create()
                    .Add(CompressedContent.Default());

This concern is part of the default configuration and will automatically be added globally if .Defaults() is used on the host.

Request Analysis

The algorithm used to compress the response is negotiated with the client via the Accept-Encoding header. If multiple algorithms are supported by the client, the server will choose the most modern one. This is determined via the Priority field of the configured compression algorithms.

Response Analysis

The concern analyzes the Content-Type of the generated response to check, whether the content can be compressed. The types enabling compression are currently fixed and cannot be modified. Responses that are already encoded (have a Content-Encoding) will not be changed.

By default, only content larger than 256 bytes will be compressed, as compression on smaller responses introduces more overhead than benefits. To change this limit, use the .MinimumSize() overload on the builder. Passing null for minimal size will always compress response content.

The compression concern will tell the algorithms to use the fastest mode available, featuring a good balance between CPU usage and resulting content size. If you would like to adjust this setting, you can use the .Level() function of the builder.

If the content served by your application is static files that rarely change, consider precompressing them ahead of time instead of paying the compression cost on every request.

Custom Algorithms

To add a custom compression algorithm to the server, you can implement the ICompressionAlgorithm interface and register the implementing class with your server builder.

using System.Buffers;
using System.IO.Compression;

using GenHTTP.Api.Content.IO;
using GenHTTP.Api.Protocol;

using GenHTTP.Modules.Compression.Providers;
using GenHTTP.Modules.IO.Streaming;

public class DeflateCompression : ICompressionAlgorithm
{
    private static readonly AlgorithmName AlgorithmName = new("deflate");

    public AlgorithmName Name => AlgorithmName;

    public string FileExtension => "zz";

    public Priority Priority => Priority.Low;

    public IResponseContent Compress(IResponseContent content, CompressionLevel level)
    {
        return new CompressedResponseContent(content, sink => new DeflateSink(sink, level), Name);
    }
    
    public Stream Decompress(Stream content) 
    {
        return new DeflateStream(content, CompressionMode.Decompress, leaveOpen: true);        
    }

}

public sealed class DeflateSink(IResponseSink sink, CompressionLevel level) : IResponseSink, IDisposable
{
    private IBufferWriter<byte>? _writer;

    public Stream Stream { get; } = new DeflateStream(sink.Stream, level, leaveOpen: false);

    public IBufferWriter<byte> Writer => _writer ??= new StreamBufferWriter(Stream);

    public void Dispose() => Stream.Dispose();

}
                        
// registration
var server = Host.Create()
                 .Handler(...)
                 .Defaults(compression: false)
                 .Compression(CompressedContent.Default().Add(new DeflateCompression()));