I'm using Nginx as a caching proxy server. I have problems with caching responses using both X-Accel-Expires and Cache-Control headers.
My upstream returns some request body with headers to nginx:
[...]
X-Accel-Expires: 60
Cache-Control: no-cache
[...]
My intent is that nginx will cache response for 60 seconds but clients will get only Cache-Control: no-cache header (so they will not cache response in the browser).
But nginx isnt caching that response. Nginx honour Cache-Control header and ignoring X-Accel-Expires header. I thought that X-Accel-Expires is "stronger" that Cache-Control but it is not.
Is there any way to change that?
I know that I can use:
proxy_ignore_headers Cache-Control;
But I cant do that because I don't have X-Accel-Expires headers in every response from upstream server.
To sum up when I return thoose headers from upstream:
X-Accel-Expires: 60
Cache-Control: no-cache
I want to cache response in nginx cache for 60s but return to clients Cache-Control: no-cache.
But when I return this:
Cache-Control: max-age=90
(without X-Accel-Expires header) I want to cache response in nginx cache for 60s and return to clients Cache-Control: max-age=90 header.
Is this possible?
Then,
X-Accel-Expires
header everytime or add it with add_header
directive (using for instance $http_cache_control
in a if statement).Cache-Control
header for caching everytime.map $upstream_http_cache_control $cache_control_value { "~^max-age=(?<duration>\d+)$" "$duration"; }
server {
listen 127.0.0.1:80; upstream nodes { server foo; } location / { if ($upstream_http_x_accel_expires = '') { add_header "X-Accel-Expires" $cache_control_value; } proxy_set_header "Host" $host; proxy_pass http://nodes; }
}
server {
server_name mydomain.com; listen X.X.X.X:80; upstream intermediate { server 127.0.0.1; } location / { proxy_set_header "Host" $host; proxy_pass http://intermediate; proxy_ignore_headers 'Cache-Control'; proxy_cache mycache; }
}
For the last case refer to the first point or use proxy_cache_valid
, but with this last paremeter you can't make the timeout dynamic. You need some coherent workflow at one point.
Thanks for answser but this isnt working. 'if' logic in this case is in action after nginx cache module decided to not to cache response. My upstream returned only: Cache-Control: 60. Nginx added X-Accel-Expires header as it should but there is no file in the cache and clients see both Cache-Control and X-Accel-Expires header in the response. So this is clear that this IF logic is placed after cache logic happens.
@Tereska Of course, you need to set an intermediate vhost. See updated answer for clarity. But keep in mind that the best way to achieve this is to correct your workflow.
WOW. this is clever :) One more thing: Cache-Control:max-age=60. How to put only value "60" (without maxage=) from Cache-Control to X-Accel-Expires (I'm refering to the IF statement). Without some regexp(?) I will end up with X-Accel-Expires: max-age=60 (and I think this will not work(?))
@Tereska Use a
map
statement and capture the right value with a regex.could you give im some example what do you mean? (it could be in pseudo code if you dont have time). thank you.