I have some image resources that are immutable and can be cached forever. Chrome seems to respect my response headers, and does not re-validate the resources:
H
Just to be more verbose let me elaborate on ETags. Technically, Firefox is handling it correctly. When an Etag is present, the client or intermediary caches need to perform a GET or HEAD ensuring the content being served hasn't changed.
The If-None-Match header tells the server what version or versions it has. If it has not changed, the server/proxy returns a 304.
You can modify the revalidation behavior by making it a weak ETag. That is done by including W/ in front of the ETags value, i.e. ETag: /W #########
. This can be handled on your server or if you can't control it by rewrite rules on your CDN.
The possible workaround for Firefox is adding the Cache-Control Immutable options. Cache-Control: Immutable. Without looking at the code in Firefox caching heuristics I can't say for sure but it should be easy to test.
Other servers will ignore the header if they don't support it.
Etags also don't work with byte-range requests. So if you don't have a specific reason for using them consider turning them off.
Put simply: Firefox revalidates cached content on browser refresh.
That used to be what all browsers did. It was probably reasonable at one time to assume that if a user was actively refreshing their page it was because something went wrong and they needed to start from scratch. Now, with the advent of sites showing real-time content, the use of "refresh" may be quite different.
Chrome and Firefox seem to be taking different paths to deal with this. Chrome's approach is to make its refresh behavior smarter and more sophisticated, while Firefox has chosen to rely on the developer explicitly indicating that a non-stale resource never needs revalidation by using the Cache-Control: immutable response header. (See this answer for more on this distinction).
If this refresh behavior is an important use case for your application (as opposed to just something you're using for debugging purposes) adding Cache-Control: immutable
should solve this problem in Firefox.