On Sep 15, 2009, at 5:30 PM, Christopher Lenz wrote:
This is a somewhat misleading description; it's not the lack of an Expires header on CouchDB responses that results in incorrect caching, it's a (really ugly) bug in the XMLHttpRequest implementation of IE6 that does this. As far as I know, the cache control headers sent by CouchDB are absolutely correct according to the HTTP specification. Unconditionally adding an Expires header (with a date in the past) just to workaround the XHR bug in IE6 *completely disables* any caching by any user agent!

One of the earlier patches did, but the current patch has no negative effect on other browsers (other than adding 20 or so bytes to the header) and brings XmlHttpRequest's behavior into line with the other browsers. Adding Expires in conjunction with the must-revalidate simply explicitly declares that any reuse of previously cached documents must be revalidated with the server. There is no time that the document is fresh and does not need revalidation. Without the Expires header, other browsers guess what we'd like them to (that the document isn't fresh) and IE 6's XmlHttpRequest uses heuristics and typically guesses that the document is fresh. Adding an Expires header in the past (or a value of 0) is explicitly mentioned in the HTTP RFC as the mechanism to mark as response as immediately stale. I kept the date in the past (though I would have preferred sending a 0) since one of the UUID tests was over-specified and would fail if it didn't have a valid date.

I've monitored the traffic and the logs before and after the patch and see exactly what I would expect. Second requests to unchanged documents get a 304 returned from the CouchDB and use the previously retrieved value on every browser I've tried. Fire up Fiddler or your favorite network monitoring tool and see for yourself.


Note also that IE6 gets cache invalidation right when you don't go through XMLHttpRequest (that is, request CouchDB documents/views directly).

A CouchDB-based application that runs on the client (CouchApp- style), and that needs to work on IE6, has the option to force all XHR requests to invalidate the cache (for example by using jQuery's "cache=false" option to AJAX requests, which simply adds an extra timestamp-valued query string parameter). In addition, it can choose to do so if, and only if, it detects to be running on IE6. And of course, applications accessing CouchDB only through server-side code do not need to care about this issue at all.

Presumably we *could* add the browser detection and the conditional addition of an Expires header to the CouchDB HTTP server, but browser detection is a really slippery slope that I think we should avoid, and IE6 is likely (or so I hope) to be pretty much extinct by the time CouchDB reaches the 1.0 mark. In any case, I'm -1 on any patch that does this unconditionally, and -0.5 on any patch that does the Expires header dance conditionally. I'd be okay with adding the cache busting trick to Futon (but again, only conditionally), and documenting the issue and workaround for CouchApps.

Cheers,

The unconditional Expires header is the simplest fix. As far as I can tell, it has no undesirable effects and accomplishes the goal. If that doesn't go in, then I'd prefer to see the header values being configurable instead of baking in other logic.

I don't want to get in a reopen war, but please reopen the bug.

Reply via email to