How to make proxy revalidate resource from origin

谁说我不能喝 提交于 2020-01-13 18:59:08

问题


I have an Nginx reverse proxy on the same machine as my origin server. I want the proxy to cache dynamic content from the origin, but when a client revalidates a resource, I want the proxy to revalidate with the origin too, and not just return a 304 to the client without checking the origin.

For example if I set max-age to 60 seconds, the proxy will happily return 304 for that period without ever checking the origin. I've set up a test where the origin generates a new etag every second, like this (using node.js express):

app.get('/dynamic/:file?', function(req, res){
  var filename = req.params.file;
  var filepath = path.join(__dirname, 'files', filename);
  res.setHeader('Cache-Control', 'public, must-revalidate, proxy-revalidate, max-age=60, s-maxage=60');
  res.setHeader('ETag', filename+etagCounter);
  res.sendfile(filepath);
  console.log('request', requestCounter++);
  console.log('etag', etagCounter);
  console.log('date', new Date().toISOString());
});

And in Nginx the route that passes this request is configured like this:

location /cache/ {
  access_log on;

  add_header Vary "Accept-Encoding";

  add_header X-AppServer $upstream_addr;           # Backend Server / Port
  add_header X-AppServer-Status $upstream_status;  # Backend HTTP Status
  add_header X-Cache $upstream_cache_status;       # HIT / MISS / BYPASS / EXPIRED

  proxy_redirect      off;
  proxy_set_header    X-Real-IP            $remote_addr;
  proxy_set_header    X-Forwarded-For      $proxy_add_x_forwarded_for;
  proxy_set_header    X-Forwarded-Proto    $scheme;
  proxy_set_header    Host                 $http_host;
  proxy_set_header    X-NginX-Proxy        true;
  proxy_set_header    Connection           "";

  proxy_cache         one;
  proxy_cache_key     $scheme$proxy_host$uri$is_args$args;

  proxy_pass http://localhost:4444/;
}

When the client talks directly to Express, I see 304s returned by Express, but when there is the proxy in between Express never returns a 304 to Nginx. Nginx serves from cache and only just gets the resource from the origin when max-age has passed.

To be sure I put the etag refresh interval at 60 seconds and the max-age at 1. As a result Nginx will get a new resource every second from the origin (without revalidating, so a 200 response), and will then return a 304 to the client until the etag changes after 60 seconds.

My conclusion is that Nginx never revalidates with the origin server. It just gets a new copy of the resource whenever it thinks it needs one according to max-age.

Is there a way to do what I want? Does it not respect the proxy-revalidate header, or am I not taking the right approach?

[EDIT]

I've since found an answer here. From this article I make up 2 solutions.

1) The must-revalidate/proxy-revalidate in the cached response should be enough for nginx to trigger a revalidate when receiving max-age=0 in a request.

2) When a client sends 'no-cache' in a CC header, the proxy should definitely do a revalidation with the origin.

From my tests both don't seem to work. For example I'm doing a request like this:

curl 'http://localhost:9088/cache/dynamic/image.jpg' -H 'If-None-Match: image.jpg0' -H 'Accept-Encoding: gzip,deflate,sdch' -H 'Host: localhost:9088' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Cache-Control: no-cache, max-age=0' -H 'Cookie: octane.sid=s%3AUa64F6fk2Pw0uwZ28e7OICyv.z2FNPYjQ7%2Fn%2F3vZGXV7B3QBYtqN%2FHzjV1e3XTuZcnmwduE4SBFEPDv3zE3zRuA4Ae705RtI6Z%2BBrqJyMveSjNA' -H 'Connection: keep-alive' -H 'If-Modified-Since: Thu, 06 Sep 2012 09:21:53 GMT' --compressed -I

It contains -H 'Cache-Control: no-cache, max-age=0', but I still get served content from the nginx cache without it checking the origin.

Is Nginx behaving bad in this regard? I'm using version 1.5.4

来源:https://stackoverflow.com/questions/19023777/how-to-make-proxy-revalidate-resource-from-origin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!