Details
-
Bug
-
Status: Closed
-
Minor
-
Resolution: Won't Fix
-
None
-
None
-
None
Description
While CouchDB's automatic ETag handling on Show/List functions is desirable 95% of the time, I keep running into situations where I want to do something handy in a documentless show function ("if all you have is a hammer...") but end up getting into trouble with cached responses.
I think the most straightforward fix is to send along any ETag header in a viewserver response instead of the default. Currently, instead of overriding the ETag header, the two headers are combined. This does "bust the cache" in some browsers if the only attempt to revalidate the first one (which happens to be that of the show function), but Firefox at least sends both back and CouchDB finds its match and responds with 304 "Not Modified". Letting a show/list function return a single garbage ETag would let it avoid having its result considered so strongly valid later.
Consider my stupid simple little public IP address reflector (https://github.com/natevw/ipcalf/blob/master/shows/address.js) or the following show:
function (doc, req)
{ return "Now is " + Date() + " and here is a unique identifier " + req.uuid + " which might have more entropy than " + Math.random(); }There are a lot of interesting/fun things that are well within JavaScript's reach in a (practically) side-effect free formatting function: different stylesheet based on user agent, SVG chart of DB stats in req.info, random quote generator... None of these are practical if the response will quickly end up locked by a cache — potentially in proxies well upstream of the client — based on an overly narrow definition (and IMO sometimes needless requirement) of idempotence.
Letting the show function "bust the cache" by providing a response ETag which CouchDB won't re-validate would be a simple way to avoid this. With my proposal above, my IP address example would simply override the ETag and avoid 304-effects altogether:
function (doc, req) {
return {headers:
, body: "Your IP address is: " + req.peer};
}
[If such a function wanted to allow for some caching benefit, it could provide an appropriate Expires header instead.]