Users hate your cache
Users don’t like caching! They want to see the changes immediately. Otherwise they get confused and write you bug tickets or flame mails. But if you do not use caching the user comes and make your CPU’s burning. If your site is down you not only get mails from your users, but also from your management.
We worked hard on the right caching strategy over months now. But there are still caches that do not get invalidated right or are cached too long and we still get complaints from our users. So we decided to integrate a feature that allows certain users to invalidate the cache on the server side. The first idea was to add a link to every page that will append a GET-parameter to the site and then avoid the cache.
Thanks to a bug ticket I remembered that certain browsers could force squid to reload the resources. The trick is that the HTTP/1.1-protocol has some features to control caching. If you press
ctrl+F5 in your browser some of this features are triggered and sent over the wire in the http-request-header. I found a great article about headers in different browsers, unfortunately it’s not correct in every case.
Request Headers in PHP
So I had to find out what these browsers in fact are sending. Sure – you could find out with a sniffer, but as I needed this data in my script anyway I tried to get them from php. As long as your php installation does run as an apache module this is pretty easy: With apache_request_header() you get an array with all header information. I did add them to our debug window and I did get something like:
Trevi_Debug_Dump::dump(array(8), 'headers') (/home/xxx/sb2/www/bootstrap.php:73) array 'Accept' => string '*/*' (length=3) 'Accept-Language' => string 'de-ch' (length=5) 'Accept-Encoding' => string 'gzip, deflate' (length=13) 'User-Agent' => string 'Mozilla/4.0 ([...]; InfoPath.1)' (length=86) 'Host' => string 'ch.sb2.leo.dev.tilllate.com' (length=27) 'Connection' => string 'Keep-Alive' (length=10) 'Cache-Control' => string 'no-cache' (length=8) 'Cookie' => string '__utma=[...]' (length=769)
So I tried this for different browsers. Unfortunately it’s specified nowhere what a browser has to send in which situation.
Internet Explorer 6 and 7 do both send only cache refresh hints on ctrl+F5. On ctrl+F5 they both send the header field ‘Cache-Control’ set to ‘no-cache’.
Firefox 3 do send the header field ‘Cache-Control’ with the value ‘max-age=0′ if the user press f5. If you press ctrl+f5 Firefox sends the ‘Cache-Control’ with ‘no-cache’ (hey it do the same as IE!) and send also a field ‘Pragma’ which is also set to ‘no-cache’.
Firefox 2 does send the header field ‘Cache-Control’ with the value ‘max-age=0′ if the user press f5. ctrl+f5 does not work.
Opera/9.62 does send ‘Cache-Control’ with the value ‘max-age=0′ after f5 and ctrl+f5 does not work.
Safari 3.1.2 behaves like Opera above.
Chrome does something quite different: ‘Cache-Control’ is always set to ‘max-age=0′, no matter if you press enter, f5 or ctrl+f5. Except if you start Chrome and enter the url and press enter.
Somehow it does look like there is still war outside. The Browser War is not over yet! Nearly every browser seams to interpret the http standard a bit different. This makes implementing software for the web quite hard, Chrome does not help at all at this point.
As my cache-invalidation-implementation is implemented only for a small user base I will make it only work for IE and FF 3.