5

I was wondering if there is a way to control lifetime of the redirects in Nginx?

We would liek to cache 301 redirects in CDN for specific amount of time, let say 20 minutes and the CDN is controlled by the standard caching headers. By default there is no Cache-control or Expires directives with the Nginx redirect. That could cause the redirect to be cached for a really long time. By having specific redirect lifetime the system could have a chance to correct itself, knowing that even "permanent" redirect change from time to time..

The other thing is that those redirects are included from the Server block, which according the nginx specification should be evaluated before locations.

I tried to add add_header Cache-Control "max-age=1200, public"; to the bottom of the redirects file, but the problem is that Cache-control gets added twice - first comes let say from the backend script and the other one added by the add_header directive..

In Apache there is the environment variable trick to control headers for rewrites:

RewriteRule /taxonomy/term/(\d+)/feed /taxonomy/term/$1 [R=301,E=expire:1] Header always set Cache-Control "store, max-age=1200" env=expire

But I'm not sure how to accomplish this in Nginx.

2 Answers 2

2

I too use the "environment variable trick" to do this in Apache and was looking for the equivalent method in nginx. It's been a few years since this question was first asked, so things may have changed since then, but I did find a way to set a default lifetime for redirects in nginx 1.14.

In a server block, you can effectively set new default Cache-Control and Expires header values for all 301 redirects by using a map variable to set the value of the expires directive based on the return status code ($status). If desired, this new default can be overridden in more specific location blocks where necessary. As an added bonus, you don't have to repeatedly specify an environment variable with every redirect like you do in Apache.

Here's an example that illustrates this, where all HTTP requests are upgraded to HTTPS using "permanent" 301 redirects that only last for an hour. An exception has been made for URI's prefixed with /override, where the 301 is left to indeed be permanent.

map $status $expires {
        default off;
        301     1h;
}

server {
        listen 80 default_server;
        server_name _;
        expires $expires;
        location /override {
                return 301 https://$host/somewhere;
                expires off;
        }
        location / {
                return 301 https://$host$request_uri;
        }
}

This gives the expected header values:

$ curl -I http://localhost
HTTP/1.1 301 Moved Permanently
Server: nginx/1.14.0 (Ubuntu)
Date: Thu, 11 Jun 2020 01:01:43 GMT
Content-Type: text/html
Content-Length: 194
Connection: keep-alive
Location: https://localhost/
Expires: Thu, 11 Jun 2020 02:01:43 GMT
Cache-Control: max-age=3600

$ curl -I http://localhost/override
HTTP/1.1 301 Moved Permanently
Server: nginx/1.14.0 (Ubuntu)
Date: Thu, 11 Jun 2020 01:01:49 GMT
Content-Type: text/html
Content-Length: 194
Connection: keep-alive
Location: https://localhost/somewhere
1

Have you tried Cache-Control flags in your nginx configuration ?

Sample configuration:

upstream yourappserver{
  server 0.0.0.0:6677;
}


proxy_cache_path  /tmp/cache levels=1:2 keys_zone=my-test-cache:8m max_size=5000m inactive=300m;

server {
    listen 80;
    server_name your.domain.tld;
    root /path/to/the/document/root/;

    access_log  /var/log/nginx/access.log;

    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_cache my-test-cache;
      proxy_cache_valid  200 404  1m;
      proxy_cache_valid 302 20m;

      proxy_cache_use_stale   error timeout invalid_header updating;
      proxy_redirect off;

      if (-f $request_filename/index.html) {
        rewrite (.*) $1/index.html break;
      }
      if (-f $request_filename.html) {
        rewrite (.*) $1.html break;
      }
      if (!-f $request_filename) {
        proxy_pass http://yourappserver;
        break;
      }
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
      root html;
    }
}

I think you are looking for this particular configuration snippet

proxy_cache_valid 302 20m;
1
  • A sample configuration does not answer the question
    – Emii Khaos
    Aug 18, 2017 at 14:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .