Opened 3 years ago

Closed 18 months ago

#746 closed defect (wontfix)

Cached objects wit expires headers in the past served up with proxy_cache_revalidate

Reported by: www.google.com/accounts/o8/id?id=AItOawmGDpcYM71Ntz-hrHOXI7cpC4p1v65aUc8 Owned by:
Priority: minor Milestone:
Component: nginx-module Version: 1.6.x
Keywords: Cc:
Sensitive: no
uname -a: Linux base.vagrant.foo.com 2.6.32-504.8.1.el6.x86_64 #1 SMP Wed Jan 28 21:11:36 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.6.2 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_spdy_module --with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

Description

When setting up a nginx reverse proxy that caches objects to the filesystem, you can get into a configuration where objects with Expires headers that expire in the past are served up indefinitely.

Steps to reproduce:

1) Setup a backend to proxy for that sends expires, etags, and last-modified headers
2) Setup nginx to proxy for that backend host. Enable a proxy_cache_path with a large inactive time, such as 24h. Enable proxy_cache_revalidate.
3) Make the first request with curl. The object will be fetched from the backend, and cached on nginx's filesystem. Note that the expires header from the backend and nginx's cached object match.
4) Wait until after the expires header timestamp has passed, and make the same request from curl. Nginx will do the right thing and revalidate the object, but if the object has the same etag on the backend with a new expires header, nginx won't update it's local cached object with the new expires timestamp.

Shouldn't nginx update it's expires header to match the backend on revalidation?

That's the core bug, but there's some other behavior going on that I can't quite figure out. Even though nginx now has an expires header in the past, it doesn't attempt to revalidate on each request after that. I'm not 100% certain, but I think only time it would attempt to revalidate was after the inactive time on the proxy_cache_path had expired.

Disabling proxy_cache_revalidate is a workaround, but not nearly as efficient.

I'm attaching a diff of what I've done to the configuration from a stock install of the CentOS 6 RPM from the nginx yum repo.

Attachments (1)

nginx.patch (6.2 KB) - added by www.google.com/accounts/o8/id?id=AItOawmGDpcYM71Ntz-hrHOXI7cpC4p1v65aUc8 3 years ago.
nginx-config.patch

Download all attachments as: .zip

Change History (2)

Changed 3 years ago by www.google.com/accounts/o8/id?id=AItOawmGDpcYM71Ntz-hrHOXI7cpC4p1v65aUc8

nginx-config.patch

comment:1 Changed 18 months ago by mdounin

  • Resolution set to wontfix
  • Status changed from new to closed

The proxy_cache_revalidate is turned off by default, in particular, because nginx doesn't try to merge headers received in 304 responses with original response headers. And there are no plans to change this in foreseeable future.

If you want to use proxy_cache_revalidate, consider using Cache-Control: max-age=... instead of (or in addition to) Expires on your backend, and/or using proxy_hide_header/expires to hide or change the header on nginx side.

Note: See TracTickets for help on using tickets.