Use brotli compression with ASP.NET Core

Brotli is a compression algorithm. In general, it provides better compression results than gzip. For instance, the size of the default page of an ASP.NET Core project using gzip is 1797 bytes, and using Brotli, it's only 1333 bytes. So it's a 25% reduction!

You can use Brotli with most of the major browsers (source):

Brotli browser support

So, it's time to support Brotli in addition to gzip!

I've already written about the gzip compression in ASP.NET Core using the ReponseCompression package: Enabling gzip compression with ASP.NET Core. Today, we'll see how to provide your own compression method, and support brotli.

Implementation

If you check the code in the CoreFX Lab repository on GitHub regulary, you may have notice there is a new project: System.IO.Compression.Brotli. This project contains an API to compress and decompress data using the Brotli algorithm. Of course, this package is a preview, and is not supported yet.

CoreFx Lab projects are not published to NuGet.org. Instead, there are published to a public MyGet repository. So, to get this package, you must declare the feed in Visual Studio:

https://dotnet.myget.org/F/dotnet-corefxlab/api/v3/index.json

Or, you can create a nuget.config at the root of the solution with the following content:

<configuration>
  <packageSources>
    <add key="dotnet-corefxlab" value="https://dotnet.myget.org/F/dotnet-corefxlab/" />
  </packageSources>
</configuration>

Then, you can add the 2 following packages:

  • System.IO.Compression.Brotli
  • Microsoft.AspNetCore.ResponseCompression

The response compression middleware look at the headers of the request and check if a compression provider can handle one of the accepted encoding. By default, only the gzip algorithm is supported. You can support custom encodings by implementing a custom compression provider. A custom provider must implement the ICompressionProvider interface. This interface contains a property with the name of the encoding, and a method to create a compression stream. The brotli package provide a BrotliStream class, so the implementation is very easy:

public class BrotliCompressionProvider : ICompressionProvider
{
    public string EncodingName => "br";
    public bool SupportsFlush => true;

    public Stream CreateStream(Stream outputStream)
    {
        return new BrotliStream(
            outputStream,
            CompressionMode.Compress,
            leaveOpen: false,
            bufferSize: 65520,
            quality: CompressionLevel.Optimal); // very costly, may not be appropriate for a web server
    }
}

Finally, you can use the custom provider:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddResponseCompression(options =>
        {
            options.Providers.Add(new BrotliCompressionProvider());
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseResponseCompression();
        app.UseStaticFiles();
        app.UseMvcWithDefaultRoute();
    }
}

You can check the server compress the response using brotli by looking at the response header:

Conclusion

The Brotli compression package is in preview, and not ready to go in production. So, use it with caution. However, this is another example of how easy it is to extend ASP.NET Core 😃 Plus, you should really monitor the corefx repository on GitHub. You may find some gems such as the Brotli compression project.