Tuesday, February 13, 2007

Firefox date handling in Page Info

Today I was researching an HTTP caching problem and I discovered what I thought was a bug. When viewing the Page Info for an HTTP resource in Firefox, there is a "Modified" and "Expires" date that should reflect the modification date of the resource and when the resource should expire from the browser's cache. Here is what I was seeing:

Modified:  Tuesday, February 13, 2007 6:38:58 PM
Expires:   Tuesday, February 13, 2007 6:38:03 PM

For the life of me, I could not understand why the modification date was after the expiration date. A helpful user wrote in with his own numbers that gave the expiration date as being a minute-and-a-half in the future of the modification date. It was supposed to expire exactly 20 seconds after it was modified. What was going on here?

Take a look at the response headers. This request was made when the local clock on my PC was exactly 00:38:00 GMT:

Date:          Wed, 14 Feb 2007 00:39:14 GMT
Last-Modified: Wed, 14 Feb 2007 00:38:58 GMT
Expires:       Wed, 14 Feb 2007 00:39:18 GMT
Cache-Control: max-age=3

See what's going on yet?

The clocks on servers and client systems can't be guaranteed to be synchronized. So when a server sends a Last-Modified or Expires date, the client can't really be sure when those events occur. HTTP solves this by including a Date header, which should match the server's clock at the time the response was sent. Browsers can then compare this clock to the client PC's clock to figure out when the server really intended the resource to expire.

Firefox is really doing the only reasonable thing it can do here. Cache expiration is something only Firefox can do. Since Firefox needs to know when, relative to its local clock, a resource should expire, it needs to compare the server's intended expiration date with its own clock. This means it has to adjust the resource's expiration date to compensate for the difference in clocks. The modification date, on the other hand, is something that's really only meaningful to the server. When Firefox decides that it needs to make a request to the server, it has to provide the Last-Modified date exactly as the server did, so that the server knows when it's appropriate to send back an updated resource, or just tell the browser to use what it already has cached.

The result? The Modified and Expires dates on the Page Info tab are showing times from the perspective of two different clocks. They cannot be compared to one another!

More reasons people don't want to deal with HTTP caching!