Configuring Cache Expiration for File System & Sitecore Media based on Production Deployments

While working with Cache configuration for our website, we found that Sitecore’s media files have ‘Expires’ and ‘ETag’ set in their cache headers. But we do not have these two settings for the File System Media like Stylesheets, Script Files and Static Image files. As a result, whenever we have a production release, users will have to refresh their cache to get the latest updates.

While working on this we found ‘MediaResponse.MaxAge’ setting for the Sitecore Media files, which we can update based on the next production release. But we do not have any such property for File System Media.

For setting the appropriate cache headers for the file system media, we will have to add custom handlers under customHandlers section and patch it into web.config file,

<handler trigger="/Assets/" handler="sitecore_filesystem_media.ashx"/>

We have our Scripts, Stylesheets etc. in the Assets folder, so url for them will contain ‘/Assets/’. We can also have separate handlers for Images, Scripts, Stylesheets etc.

<handler trigger=".png" handler="sitecore_filesystem_images.ashx"/>
<handler trigger=".js" handler="sitecore_filesystem_scripts.ashx"/>
<handler trigger=".css" handler="sitecore_filesystem_stylesheets.ashx"/>

And the handler definition has to be added under system.webServer/handlers

<add verb="*" path="sitecore_filesystem_media.ashx" type="SitecoreWebsite.Utilites .MediaRequest.FileSystemMediaRequestHandler, SitecoreWebsite.Utilites" name="Sitecore.FileSystemMedia"/>

And our custom Handler looks like this,

public class FileSystemMediaRequestHandler : IHttpHandler, IRequiresSessionState
{
    public bool IsReusable
    {
        get { return true; }
    }
    public void ProcessRequest(HttpContext context)
    {
        HttpCachePolicy cache = context.Response.Cache;
//Get the Next Production Deployment Date from Sitecore
        DateTime nextProductionDeployment = ((DateField)Utilities.GetItem(....).Fields["Next Production Deployment"]).DateTime;
        if(nextProductionDeployment < DateTime.Now)
        {
//Set Default Cache Expiration if the Next Production Deployment date is not updated
            cache.SetMaxAge(new TimeSpan(7, 0, 0, 0));
            cache.SetExpires(DateTime.Now.AddDays(7));
        }
        else
        {
            TimeSpan span = nextProductionDeployment - DateTime.Now;
            cache.SetMaxAge(span);
            cache.SetExpires(nextProductionDeployment);
        }

        cache.SetCacheability(HttpCacheability.Private);
        context.Response.ContentType = MimeMapping.GetMimeMapping(context.Request.RawUrl);
        context.Response.WriteFile(context.Request.RawUrl);
        context.Response.End();
    }
}

I have kept the Next Production Deployment Date in Sitecore, and the expiration date of every media is calculated based on this value. We will have to add this value to a Session Variable(by implementing IRequiresSessionState interface) to avoid frequent hits to Sitecore.

We will also have to set the parameters like Last Modified Date and ETag for every media’s cache headers.

The same configuration can be followed for Sitecore Media too.

We can create our custom handler for Sitecore’s MediaRequest and override the SendMediaHeaders Method. Necessary changes have to be made to web.config(sitecore_media.ashx)

public class CustomMediaRequestHandler : MediaRequestHandler, IRequiresSessionState
{
     protected override void SendMediaHeaders(Media media, HttpContext context)
     {
         //Cache Configuration for Sitecore Media goes here..
     }
}

Thus we have created a common place in Sitecore, for updating the Cache Expiration & related configurations for Sitecore & FileSystem Media.

But what if we have an unplanned production move, our configurations will have to accommodate that as well. For this we can create another date field in Sitecore (may be ‘Last Production Modified Date’) which will be updated when we do any changes to Sitecore Media or File System Media. We can store this date in a Cookie in user’s machine, and whenever cookie value and Sitecore date field value does not match, we will have to do a Response.Redirect(may be Sitecore.WebUtil.Redirect) or window.location.reload() to the same page. This will automatically download the latest version of media files along with our Cache Headers.

Originally Posted at:  https://www.nttdatasitecore.com/Blog/2016/August/Configuring-Cache-Expiration-for-File-System-and-Sitecore-Media-based-on-Production-Deployments

Leave a Reply

Your email address will not be published. Required fields are marked *