2

I have a requirement where I need to support downgrading of my server code.

I have the following line in my nginx configuration file, indicating that the browser can cache the page but has to validate with server to check if the file changed.

add_header Cache-Control "no-cache";

This setup works perfectly fine for me with all the upgrades done on my server code.

But when it comes to downgrading a resource to an older version, when the browser tries to validate the resource change, nginx says that the resource hasn't changed, so the browser shows the cached(newer) resource instead of the downgraded(older) resource.

As a workaround, I could use the following setting to disable cache completely, but its not efficient, and I would like to have caching.

add_header Cache-Control "no-store";

So how would I make nginx recognize downgrades??

Schu
  • 123

2 Answers2

1

In a no-cache scenario, the browser will usually issue an If-Modified-Since header with a GET request, to see if the file in question has changed from the cached copy.

The server will either:

  1. return a 304 - Not Modified response
  2. return another code:
    • 200 - OK if the modified date on the server is later than that passed with the header
    • Other - any other code that might be returned (4xx, 5xx, etc)

Nginx will use the modified timestamp on the file it is serving to generate the Last Modified header and for comparison against If-Modified-Since.

Due to this, updating the timestamp of a file with touch /path/to/myfile.ext will cause nginx to identify it as having been modified after the If-Modified-Since date and will allow nginx to serve the file.

Alternatively, you should be able to force a re-fetch by explicitly specifying a 'Last Modified' header in your nginx config that is after the anticipated date of If-Modified-Since. In your scenario, this would essentially entail:

  1. Downgrade your code
  2. Modify nginx config with current date (e.g.): add_header Last-Modified Mon, 09 Jan 2012 17:07:00 GMT
  3. Reload nginx

An important point of mention is that if your static assets change after this, the hard-coded header will not reflect the change (i.e. even when you 'upgrade' your code, you will still have to manually alter the config.

cyberx86
  • 21,105
0

First of all, "no-cache" doesn't necessarily mean what you think it means in practice. I suspect you really want to use "Cache-Control: max-age=0, must-revalidate". Some browsers (Firefox) incorrectly treat "no-cache" as an equivalent of "no-store", and don't cache anything on disk at all. They simply re-fetch all content from the source at every page load, which is a terrible waste of bandwidth and sucks for the user experience.

Secondly, your particular use case is exactly what ETags were designed for, rather than the simple forward-only date logic that is used without them. (The entire linked site is great reading on caching, not just on e-tags).

Finally, you should consider naming your resources with some form of date identifier (or better yet content hash) so that you never have to worry about this sort of thing. You can then set cache-control to 1 year. This requires workflow changes and build scripts though for many sites to rename files and replace links. But that is what Google and the other big boys do...

rmalayter
  • 3,832