Setting a specific Brotli compression level when using response compression in ASP.NET Core

Brotli can compress HTML, CSS and JS files more than Gzip. If you can’t enable Brotli compression on the server level but want to use it in your ASP.NET Core app you can use the response compression middleware to enable it from your Startup.cs file. Setup is easy and looks like below..

Setting up MVC response compression

Note the app.UseResponseCompression() in the Configure method needs to be before app.UseStaticFiles() as otherwise headers have already been sent. The default setup above will use Brotli if the client supports it else it will use Gzip if it’s supported. By default the Brotli compression provider will be set to a compression level of 1 (fastest).

The compression level corresponds to how aggressive an algorithm will compress a document. Brotli has 11 levels, 1 being the fastest but least compressed and 11 being the most compressed but also the slowest. Brotli at its highest level (11) is extremely slow compared to Gzip at its highest level (9). Slow compression is fine for static CSS/JS files which we can compress ahead of time. For on the fly compression (eg. dynamic web pages) slow speeds can negatively impact web app performance..

SO

.. for Brotli compression to be advantageous over Gzip we need to find the compression level which gives us the best balance between compression amount and speed..

BUT

the problem with the Brotli compression provider in ASP.NET Core is that it only has three options in its enum for setting the level…

ResponseCompression Options

There is no enum option for the best balance between compression and speed. In this case we can just set the level with a number directly…

Setting Brotli Level

You need to experiment with different levels but a number of resources seem to be agreeing on level 4 or 5 as being the sweet spot…

https://blogs.akamai.com/2016/02/understanding-brotlis-potential.html

https://paulcalvano.com/2018-07-25-brotli-compression-how-much-will-it-reduce-your-content

https://quixdb.github.io/squash-benchmark/#results-table

Of course for your static content such as CS, JS, Fonts etc. compress to the max with 11. This will give you significant byte savings over Gzip.

 

Forms authentication failed for the request. Reason: The ticket supplied was invalid

If your using forms authentication in .net and the application that creates the authentication cookie is different than the one that consumes it (i.e. Web farm scenario), the consuming application may not be able to decrypt the authentication token in the cookie and hence you might see something similar to ‘Forms authentication failed for the request. Reason: The ticket supplied was invalid’ in your event log. I had this recently and two common causes were:

  1. Machine key is different between application creating the authentication cookie and the application(s) using it.
    Keys must match. You can edit machine keys through IIS (as in below image) or directly through the web.config. Restart IIS/App pool shouldn’t be required.

image002

  1. Application creating the authentication cookie and the application(s) using it use a different cryptography core due to one targeting .net 4.5 and the other targeting 2.0 or 4.0. The method of decrypting tokens has changed since 4.5 and so an authentication token created by an application targeting 2.0/4.0 cannot be validated by an application targeting 4.5. The 4.5 cryptographic core is opt in (so not to break 2.0/4.0 applications running on machines which happen to have 4.5 installed) but the Visual Studio 4.5 project template includes one of the two different tags required to opt-in in the generated web.config. In our case our login app was a 2.0 app, but our new app was targeting 4.5.1 and so the default web.config included the following tag:

    <httpRuntime targetFramework=”4.5.1″ />

    which meant our new 4.5.1 app couldn’t decrypt the generated auth cookie. We simply changed that to <httpRuntime /> and things worked then. The second way to opt in is via the machinekey tag i.e:

    <machineKey compatibilityMode=”Framework45″ />

    so if you having problems decrypting make sure your apps have compatible runtimes set.

Related Links

Cryptographic Improvements in ASP.NET 4.5, pt. 2 – Great blog post detailing the cryptographic core changes in 4.5 and how to preserve compatibility with older versions of the framework.