12

Even though I send "cache-control: must-revalidate" Google Chrome uses a locally cached page when using the back and forth button in the browser.

This is part of the original response:

HTTP/1.1 200 OK
cache-control: private, must-revalidate
etag: "c9239b5d4b98949f8469a05062e05bb999d7512e"
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8

If I refresh the page I get a "HTTP/1.1 304 Not Modified" response but when I use the back button I get the following response:

Request URL:example.com
Request Method:GET
Status Code:200 OK (from cache)

The response I'm looking for is 304 or 200 OK, is it possible to achieve this?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Dennis
  • 3,448
  • 8
  • 38
  • 45

4 Answers4

23

When using the back and forward buttons, the key Cache-Control directive to prevent the browser returning a cached copy of the page is no-store.

Nothing else will help, and nothing else is needed. Your Cache-Control header can simply be:

Cache-Control: no-store

There are two exceptions to this though.

  1. Opera and Safari won't revalidate no matter what headers you set (at least the versions I've tested). If you open the page in a new tab, that copy will be fresh, but the original tab will continue to show the stale version when navigating back and forth until you refresh or re-enter the url.
  2. Firefox appears to have a bug in the caching of the first page that is opened (i.e. when there is no back button). All subsequent instances of the page will refresh as you navigate back and forth, but once you backup all the way to the topmost page, it can often still be showing its initial stale copy.

Finally, I should note that using this directive is not advisable in general, since it obviously has a significant impact on bandwidth usage. The browser can't even take advantage of Etags to get a 304 Not Modified response, because it will have no stored copy to use in the event a 304 response is received.

James Holderness
  • 22,721
  • 2
  • 40
  • 52
  • 1
    So basically if you want the back/forth button to work you can't take advantage of etags? – Dennis May 12 '13 at 23:01
  • http://madhatted.com/2013/6/16/you-do-not-understand-browser-history contains an interesting discussion of the situation. – Gili May 17 '14 at 05:08
  • 100 points. "The browser can't even take advantage of `Etags`" that was the answer I'm looking for, why Etags don't work. – rabudde Jan 16 '16 at 14:35
  • Actually, chrome somehow apply a algorithm behavior above all cache-related headers, so ETag may not work and return 304 – Rick Luo Jan 25 '21 at 07:12
6

The "must-revalidate" directive applies only after the response is stale (RFC2616, sec 14.9.4). Since the response contains neither an "Expires" header nor a "max-age" directive, the browser might have treated the response as still fresh and accordingly returned the cached copy. To prevent this you should include "max-age: 0" in the Cache-Control header (and possibly an Expires header containing a date in the past), so that the cached response becomes stale immediately. Alternatively, to prevent caching, use the "no-cache" directive instead of "must-revalidate".

Community
  • 1
  • 1
Peter O.
  • 32,158
  • 14
  • 82
  • 96
  • 2
    From 13.2.4 of RFC2616: "The max-age directive takes priority over Expires". You don't need both. And in any event, none of this will prevent the browser showing a stale copy when navigating with the back button. – James Holderness May 12 '13 at 11:55
  • I just confirmed James comment, the solution doesn't work with the back button. – Dennis May 12 '13 at 22:58
3

The no-store cache directive can be used to instruct the browser not to write pages to the disk cache. Combined with no-cache this should ensure all browsers will fetch the resource from upstream and not from disk.

Cache-Control: private, no-cache, no-store

SpliFF
  • 38,186
  • 16
  • 91
  • 120
  • Except I want the browser to revalidate the etag when navigating back and forth. – Dennis May 12 '13 at 23:07
  • 2
    That would violate RFC2616 section 13.13 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html) which specifies browsers should NOT revalidate: "History mechanisms and caches are different. In particular history mechanisms SHOULD NOT try to show a semantically transparent view of the current state of a resource. Rather, a history mechanism is meant to show exactly what the user saw at the time when the resource was retrieved." Browsers that don't revalidate or fetch expired pages accessed via the back button are actually doing the RIGHT thing - it's just not what you want. – SpliFF May 14 '13 at 04:56
  • 1
    Only `no-store` works because the browser has no choice, it has no local copy to display so it HAS to fetch it upstream. – SpliFF May 14 '13 at 04:57
0

The cache control is not set, forcing the browser to use the default. (Read more about the cache options here: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache)

In order to reevaluate the cache you must configure the server to send the Cache-Control: no-cache header; or the browser/client by setting the Request.cache = 'no-cache' option. This option alone is enough for the ETag to be used correctly.

enisdenjo
  • 706
  • 9
  • 21