Careful when using the Cache-Control Header UI in IIS 7.x!

I was just reading Eric Lawrence's blog on Cache headers. In it Eric describes that it's necessary to use sensible values for the Max-Age headers because IE and several browsers don't like values greater than the size of a signed 32-Bit Integer, i.e. 2,147,483,647. Bigger values result in the content not being cached at all. Using the max 32-Bit integer value (2,147,483,647) is more than enough though. It caches the content for more than 68 years (max-age is using seconds so you divide 2,147,483,647 by 60 seconds by 60 minutes by 24 hours by 365 days which gets us to 68 years).

As an IIS guy I asked myself if the IIS User Interface does the right thing when it comes to this header. Unfortunately it doesn't.

Cache-Control User Interface

The Cache-Control User Interface is somewhat hidden behind the "HTTP Response Headers" icon.

image

Clicking the icon shows existing response headers in the center. It offers the "Actions" menu on the right side. By clicking "Set Common Headers" the resulting dialog page will allow the configuration of the Cache-Control headers.

image    image

The Cache-Control dialog allows the configuration in seconds, minutes, hours or days. The value is stored as a timespan value in the IIS configuration system. In a perfect world the IIS User Interface would only allow values up to the magic 2 million (max 32-Bit signed integer) so that all browsers understand the max-age value. The world is not perfect though :(. The underlying base data type for a timespan value is a 64-Bit integer representing ticks (one tick is hundred nanoseconds, i.e. a millisecond has 10,000 ticks). The Cache-Control dialog allows values up to the max value of the timespan data type. The max is 922,337,203,685 seconds, i.e. roughly 15 billion minutes or 256 million hours or 10 million days or roughly 29247 years. Values far bigger than what web browsers understand in a Cache-Control header!

 image

What the IIS run-time does with large timespan values

When the underlying IIS run-time reads the max-age timespan value it converts it to an unsigned 32-Bit integer - no questions asked. This doesn't work too well for two reasons:

1) Large timespan's simply don't fit into a 32-Bit integer and we end up doing a modulo operation. Using the max value for seconds (922,337,203,685) for example will set the max-age header value to 3,214,202,341 which is 922,337,203,685 mod 4,294,967,295.

2) Due to the issues Eric described in his blog post the IIS run-time should not set the header if the value is larger than a 32-Bit signed integer.  

We'll fix this issue in future IIS version - but until then Eric's advise holds true: use sensible values for your cache headers!

No Comments