ARR – dynamically disable disk caching for certain requests (authenticated users)

arrcache

This is about Application Request Routing and dynamically disabling disk caching for certain requests (where the requests come from authenticated users; whether they're authenticated can be decided by custom code).

In my setup there is a server running ARR, dispatching requests to an ASP.NET MVC site on a different server. The site uses Forms Authentication (and sometimes HTTP basic authentication), thus authentication happens on the MVC site, not in ARR: basically when the user authenticates the site creates a Forms Authentication cookie.

I'd like the following to happen in ARR:

  • Do output caching for anonymous users.
  • For authenticated users only cache static files (e.g. .css,, .js, .jpg files) and don't cache dynamic pages.

How is it possible to have a cache configuration rule for this scenario? I have tried multiple ways:

  • Cache headers: the cache control headers sent by the MVC app are not usable here, because imagine this: page 1 is in the cache of ARR. User authenticates and visits page 1. The MVC app would send a no-cache header but the request is not reaching it, so the user gets the cached version.
  • No-cache URLs: I though probably defining that URLs with "no-arr-cache" in them shouldn't be cached would work with URL rewriting, i.e. with a custom URL Rewrite provider I'd rewrite authenticated requests to …?no-arr-cache. Apart from ARR cache control rules not caring about query strings the issue is that ARR only takes the requested URLs into account when a cache configuration rule is evaluated, not the rewritten URL.

Thank you in advance!

I cross-posted this from the IIS forums because nobody replied there.

Best Answer

This is how I solved it.

We have to keep the following premises in mind:

  • ARR identifies cached items with their URL (that, depending on the configuration, include the query string; this should be the config).
  • During a request ARR can be instructed not to cache the output of the current request.
  • If the current request's (URL's) output was cached before then there is no way I know of to instruct ARR not to use the cached version.

The big idea is to change the request's URL, or rather, rewrite it differently with IIS URL Rewrite depending whether the user is authenticated or not. Unauthenticated users get all the pages served with e.g. /my-page?authenticated=false and authenticated ones with /my-page?authenticated=true. Pages will be cached only for anonymous users so ARR won't find any matching cache entry for authenticated users. Thus, the third point is solved. On the downside the query string you attach to the URLs can appear in the HTML body, those should be stripped out with IIS URL Rewrite.

To instruct ARR not to cache the current request set the ARR_CACHE_CONTROL_OVERRIDE server variable to "1,no-cache" (you can do this from rewrite rules).

You can detect whether the user is authenticated from an IIS URL Rewrite IRewriteProvider (see tutorial), i.e. you can use the output of such a provider to rewrite the URL differently for authenticated and anonymous users.

Hope that helps somebody.