Client Cache Fingerprinting

Topics: Customizing Orchard
Jun 20, 2014 at 3:33 PM
Edited Jun 20, 2014 at 3:33 PM
I would like to implement Mads Kristensen's cache busting solution: http://madskristensen.net/post/cache-busting-in-aspnet in Orchard.

It defined an extension method Fingerprint.Tag(), which inserts the last-modified date into the URL. It also modifies system.webServer with a rewrite rule that remove the last modified-date.

What's the Orchard Way to implement this? Here's my initial plan:
  1. create a module
  2. put the extension method into the module
  3. modify the system.webServer in the module
  4. use the extension method throughout
Might it be better to replace step (2) with an override of a ResourceManager method? What about replacing step (3) with a new MVC route?
Jun 20, 2014 at 5:55 PM
Edited Jun 20, 2014 at 6:00 PM
I am currently trying to extend ResourceManager as follows:
using Autofac.Features.Metadata;
using Orchard.Environment.Extensions;
using Orchard.UI.Resources;
using System.Collections.Generic;
namespace BigFont.FingerPrint
{
    [OrchardSuppressDependency("Orchard.UI.Resources.ResourceManager")]
    public class FingerPrintResourceManager : ResourceManager
    {
        public FingerPrintResourceManager(
            IEnumerable<Meta<IResourceManifestProvider>> resourceProviders)
            : base(resourceProviders)
        {
            System.Diagnostics.Debugger.Break();
        }
    }
}
One of the problems is that, if another module implements [OrchardSuppressDependency("Orchard.UI.Resources.ResourceManager")], then either my ResourceManager.ctor implementation (or theirs) doesn't get hit. Is there a way to do this so that all of the ResourceManagers work?

For instance, if I define the above code, and also install the Piedone.Combinator Orchard Module, which suppresses the ResourceManager too, then only one of the implementations runs.
Developer
Jun 20, 2014 at 9:33 PM
Combinator adds such a cache busting parameter to processed resources so you don't need that if you're already using Combinator.
Jun 21, 2014 at 1:25 AM
That's good to know. I would like to build my own solution, thought, that doesn't use a query string parameter for fingerprinting.
Developer
Jun 21, 2014 at 1:31 AM
Do you want to use a URL segment ("directory") for that? If yes, why is it better than a query string parameter?
Jun 21, 2014 at 2:59 AM
Don't include a query string in the URL for static resources.
Most proxies, most notably Squid up through version 3.0, do not cache resources with a "?" in their URL. To enable proxy caching for these resources, remove query strings from references to static resources, and instead encode the parameters into the file names themselves.
Developer
Jun 21, 2014 at 9:31 PM
Edited Jun 21, 2014 at 9:32 PM
After reading these arguments and also these: http://stackoverflow.com/questions/1330011/cdn-and-urls-with-query-strings I'm not sure it's worth the effort. It seems that Amazon, Azure and Akamai CDNs all have support for query string parameters, probably other CDNs too (I also know about CloudFlare and Highwinds).

As for proxies I personally doubt that there is any maintstrem proxy server that can't deal with this (but can't back this up); also Squid 3.0 was first released in 2006 (!) and last in 2011 (see: http://www.squid-cache.org/Versions/v3/3.0/) so I'd argue if Squid is the main point here, it's a deprecated one.

That said this can be implemented in a relative straightforward way by storing resources in actual folders containing their timestamp, but this needs an in-depth modification of how Combinator stored and retrieves cache files.
Jun 23, 2014 at 1:52 AM
Edited Jun 23, 2014 at 1:57 AM
Thanks for talking this over with me. I'm not sure it's worth the effort either.

You wrote that
this can be implemented in a relative straightforward way by storing resources in actual folders containing their timestamp
That's similar to the implementation that Mads Kristensen recommends, but his method uses URL rewriting to avoid actual folders.

In any case, I'm going to experiment with Mads' method both in Orchard and some non-Orchard sites that I've built, because I have some spare time, and would like to learn more about both HTTP caching and Orchard.
Developer
Jun 23, 2014 at 1:17 PM
Since Combinator uses Media for file storage, what doesn't necessarily support URL rewriting (as it can use some external storage with direct file access, like Blob storage) it's better (and also simpler I think) to use actual folders, since files are automatically generated anyway. But please tell what you've come up with, if the folder technique is definitely better I'll modify the implementation in Combinator.
Jun 24, 2014 at 3:12 AM
Sure. I'll let you know how it goes. This is a side project, so it will take me some time as I learn about how Orchard handles resources, routing, and url rewriting.

Currently, I use your Combinator module. It works well out of the box.
Nov 16, 2014 at 10:02 AM
Hi ShaunLuttin

I also really like Mads Kristensen's cache busting solution, and wondered whether you ever managed to successfully implement it into an Orchard project?

Many thanks
Nov 16, 2014 at 11:44 PM
Hi Norman,

I haven't implemented this, unfortunately. Thank you for your interest. Mads solution is neat, because if we change a resource, the cache clearing process is automatic. I really like that aspect. Maybe someday I will get around to implementing this.

Shaun
Nov 17, 2014 at 8:49 AM
Thanks Shaun for coming back so quickly.

I had an "albeit" rudimentary tinker with it over the weekend, alas to no avail :(

If you do ever manage to implement such a feature, I would be interested. In the meantime Piedone's excellent Combinator module, seems the best way to go.

All the best

Clive Norman