Enabling gzip compression with ASP.NET Core

Brouillon

À venir

0 comment

In the last post, I talk about improving performance of a web application by caching static resources. Another great performance improvement, is about compressing response. Main browsers support deflate, gzip, and more recently brotli.

If you host your ASP.NET Core application using IIS or Nginx, you may already take advantages of the compression. However, if you do not use a reverse proxy that provides response compression, or do not want to use the compression provided by those tools, the ASP.NET Core team provides a middleware to handle response compression.

Configure response compression

  1. Install the NuGet package Microsoft.AspNetCore.ResponseCompression (Nuget, GitHub)
  2. Edit the ConfigureServices method in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.Configure<GzipCompressionProviderOptions>(options => options.Level = System.IO.Compression.CompressionLevel.Optimal);
    services.AddResponseCompression();
}
  1. Add the middleware in the pipeline
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseResponseCompression();

    app.UseStaticFiles();
    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}
  1. Let's have a look using Chrome

Using response compression, the page size is reduced by about 50% (580kB to 205kB). This is great, but this can be improved. Indeed, looking at the screenshot, you may point out that some compressible resources, such as svg files, are not compressed.

Compressing more files

The middleware identifies the compressible resources by their mime types. By default, only text, html, css, js and json files are compressed. You'll find the full list on GitHub.

In our case, we want the SVG files to be handled by the middleware, so let's change the configuration:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<GzipCompressionProviderOptions>(options => options.Level = System.IO.Compression.CompressionLevel.Optimal);

    services.AddResponseCompression(options =>
    {
        options.MimeTypes = new[]
        {
            // Default
            "text/plain",
            "text/css",
            "application/javascript",
            "text/html",
            "application/xml",
            "text/xml",
            "application/json",
            "text/json",
            // Custom
            "image/svg+xml"
        };
    });
}

image

Performance

Concerning performance, the middleware is about 28% slower than the IIS compression (source). Additionally, IIS or nginx has a threshold for compression to avoid compressing very small files. This setting does not exist yet, but may come in a future (GitHub issue).

Security

As always, you should care about security. Some known attacks, such as BREACH which exploits HTTP-layer compression, allow the attacker to guess some secrets. In the case of BREACH, the site is vulnerable if (source):

  • Your page is served with HTTP compression enabled (GZIP / DEFLATE)
  • Your page reflects user data via query string parameters, POST...
  • Your application page serves PII (Personable identifiable information), a CSRF token, sensitive data...

In this case, you should disable compression or use a mitigation. If you know what you are doing, you can enable the compression for HTTPS requests:

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

    services.Configure<GzipCompressionProviderOptions>(options => options.Level = System.IO.Compression.CompressionLevel.Optimal);

    services.AddResponseCompression(options =>
    {
        options.EnableForHttps = true;
    });
}

Conclusion

Using compression is very important to reduce the size of pages, and so reduce the loading time. The reponse compression middleware is easy to use (2 lines of code). Don't forget to use Fiddler or the developper console of your favorite browser to validate that all compressible resources are indeed compressed. And if you care about performance, you should use the response compression provided by IIS or nginx. Last but not least, you can add other compression algorithms, such as Brotli. You'll find a great sample on the following blog post.

Gérald Barré