When I unset the
Last-Modified header in Apache (
ETags are also disabled), Firefox (4.01) will not cache any file regardless of whether I set a future
Expires header or enable the
So is the
Last-Modified (and/or an
ETag) header required for browser caching?
If no validator (an ETag or Last-Modified header) is present on a response, and it doesn’t have any explicit freshness information, it will be considered uncacheable.
... well, if by "Freshness Information" they mean "Cache-Control" or "Expires" header, Firefox should be caching without the Last-Modified header.
EDIT FOR FURTHER FIREFOX INFO
Note that no attempt to generate a 304 on any PHP file served by Apache 2.2 in Firefox 4.01 is successful (reload, fresh visit, etc.) without a
Last-Modified header, regardless of any combination being set of a valid caching
Cache-Control header, the
Expires header or both headers.
foo.php: content of this file simply echoes 'Hello World'.
HTTP/1.1 200 OK Date: Mon, 06 Jun 2011 14:04:58 GMT Server: Apache Cache-Control: public, max-age=3600 Expires: Fri, 01 Jul 2011 21:23:55 GMT Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 1594 Keep-Alive: timeout=10, max=500 Connection: Keep-Alive Content-Type: text/html; charset=utf-8
EDIT FOR EVEN MORE STRANGE FIREFOX 4.01 FINDINGS
Even stranger, based on what I've seen with Firefox 4.01, no form of server-side cache control headers (Expires and/or Cache-Control) influence Firefox's caching behavior. Firefox only cares about Freshness information (Etag or Last-Modified).
In summary, if the file has been modified, Firefox reloads it, regardless of any Expires or Cache-Control headers. If the file doesn't contain any Freshness information, Firefox reloads it no matter what.
If anyone finds out differently in their observations, please update me.
From this link:
13.2.1 Server-Specified Expiration
An expiration time cannot be used to force a user agent to refresh its display or reload a resource; its semantics apply only to caching mechanisms, and such mechanisms need only check a resource's expiration status when a new request for that resource is initiated. See section 13.13 for an explanation of the difference between caches and history mechanisms.