Saturday, 18 February 2006
Invalidating Caches with POST
Have you ever posted a comment to a blog, found it missing, so you re-posted it, only to find two entries? Annoying, huh?
Aaron pinged me the other day with this problem, and I responded that the Right way to do this is to POST to the same resource (i.e., the blog entry), so that the POST invalidates the cache.
HTTP has this to say about the matter;
Some HTTP methods MUST cause a cache to invalidate an entity. This is either the entity referred to by the Request-URI, or by the Location or Content-Location headers (if present). These methods are: - PUT - DELETE - POST In order to prevent denial of service attacks, an invalidation based on the URI in a Location or Content-Location header MUST only be performed if the host part is the same as in the Request-URI. A cache that passes through requests for methods it does not understand SHOULD invalidate any entities referred to by the Request-URI.
I’d forgot that it wasn’t just on the Request-URI, but this makes total sense; each of these situations results in anything that’s been cached to be invalid, and while you can’t guarantee that all caches around the world will invalidate them, implementations should do what they can (especially browser caches, because it’s likely the user will make more requests soon).
As is hopefully obvious from our blog example, this isn’t an uncommon situation; it’s a very useful pattern of use for HTTP.
That’s fine in theory…
As we discussed this, I realised that this was how it’s supposed to work, but considering how legendarily bad some browser cache implementations are, it might not be how it actually works.
Having done some automated browser testing recently, it was easy to whip up a couple of tests for these requirements. I’ve moved all of the caching-related testing into one page; while it uses XMLHttpRequest, these results should be valid for most any implementation, as the same cache as the normal browser should be used.
What are the results so far? Safari seems OK for these purposes (even unknown methods), while Firefox gloriously fails all of the invalidation tests. Unsurprisingly, neither actually caches fresh POST responses, which would be useful in some situations. I’ve filed a bug.
I don’t have IE handy, can someone test it and tell us the results in comments?