When Paste 1.7.2's fileapp.DataApp.get method detects either an IF_NONE_MATCH or
an IF_MODIFIED_SINCE header in a request, the etags sent by the client are
matched against the current content etag. If any client etag / modified time
matches the content etag / modified time, a bit of code iterates over all the
defined "entity" headers, deleting any that exist in the current header list.
One of these deleted entity headers happens to be "Expires".
For some unknown reason, although it doesn't appear to be spec-compliant for an
HTTP 1.1 request, under this condition, if an "Expires" header is not sent back
in the 304 response by fileapp (even though Cache-Control: max-age *is* sent
back), Firefox will continually re-request the resource (using a conditional
get) on each subsequent request "forever".
Firefox just "forgets" that it's OK to not continually revalidate even though
the Cache-Control: max-age header tells it all it needs to know. This
effectively destroys all caching for a client that gets itself into this
situation. Note that I've made sure there's no "must-revalidate" in the
response that would be mucking things up.
If the Expires header is *not* removed, however, Firefox will cache the
semantics of the 304 and not make any more conditional gets (presumably until
the expiry time). This is the desired behavior, and is what I see under Safari
even when the Expires header is not set.
So. Basically I think I'd like to return an Expires header from DataApp.get
even though it's not required by the HTTP/1.1 spec when Cache-Control: max-age
is set as a workaround for what I consider to be a Firefox bug.
If I had my druthers, I'd probably disable etags altogether, mostly because I
don't think I understand them very well, and it might remove one vector of
complexity. But that would require basically reimplementing FileApp, and it
wouldn't help with the IF_MODIFIED_SINCE case either so it's probably just a
digression.
So I'd like to come up with something short of actually cutting and pasting that
entire module into my own code to work around this issue. Since it's a bit
frameworked-out, it's not easy to know which knobs to turn to bail me out,
though. I *could* change the "category" of the Expires type in httpheaders (or
at least monkeypatch its result). But I don't really understand how "correct"
those classifications are or are meant to be. Any suggestions about which knobs
to twist here short of just copying it all over to my local app?
- C
- C