0

I have about 5 sites running on different ports via reverse proxy and accessible under different sub domains. Some of these sites are setting the expires (/ cache-control max age header) by themselves and don't require this to be managed, however some do not.

For the ones that I do not, I want to specify expires for static content (as per https://github.com/h5bp/server-configs/blob/master/nginx.conf), however I cannot find a way to do this without duplicating this logic in every server. For a single server I know I can do it like this:

 server {
listen 80;

server_name sub.domain.com;

location \ {
    proxy_pass  http://localhost:1234/;
}

# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html|xml|json)$ {
  proxy_pass    http://localhost:1234/;
  expires -1;
  access_log logs/static.log;
}

# Feed
location ~* \.(?:rss|atom)$ {
  proxy_pass    http://localhost:1234/;
  expires 1h;
  add_header Cache-Control "public";
}

# Favicon
location ~* \.ico$ {
  proxy_pass    http://localhost:1234/;
  expires 1w;
  access_log off;
  add_header Cache-Control "public";
}

# Media: images, video, audio, HTC, WebFonts
location ~* \.(?:jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|eot|mp4|ogg|ogv|webm)$ {
  proxy_pass    http://localhost:1234/;
  expires 1M;
  access_log off;
  add_header Cache-Control "public";
}

# CSS and Javascript
location ~* \.(?:css|js)$ {
  proxy_pass    http://localhost:1234/;
  expires 1Y;
  access_log off;
  add_header Cache-Control "public";
}
}

This sucks because:

  • the proxy_pass is duplicated for each location block
  • which also means I can't stick this in an external file and include it for any site that requires it.

If I have 2 sites that require this, I seem to have no choice but to duplicate the whole thing changing the proxy_pass for each location.

Is there a way to achieve 'write once use many' for the expires header (and proxy_pass) logic?

1 Answer 1

1

nginx can do inclusion, with include path-to-file; markup.

You can also use if instead of location this case, so I'd try something like this:

server {
    listen 80;
    server_name sub.domain.com;

    location / {
        if ( $uri ~* \.(?:manifest|appcache|html|xml|json)$ ) {
            expires -1;
            access_log logs/static.log;
        }

        if ( $uri ~* \.(?:rss|atom|ico|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|eot|mp4|ogg|ogv|webm|css|js) ) {
            add_header Cache-Control "public";
        }

        if ( $uri ~* \.(?:ico|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|eot|mp4|ogg|ogv|webm|css|js) ) {
            access_log off;
        }

        if ( $uri ~* \.(?:rss|atom) ) {
            expires 1h;
        }

        if ( $uri ~* \.(?:ico) ) {
            expires 1w;
        }

        if ( $uri ~* \.(?:jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|eot|mp4|ogg|ogv|webm) ) {
            expires 1M;
        }

        if ( $uri ~* \.(?:css|js) ) {
            expires 1Y;
        }

        try_files @proxy;
    }

    location @proxy {
        proxy_pass  http://localhost:1234/;
    }
}

I'm not able to test it right now, but with slight modifications this should work.

6
  • 1
    wiki.nginx.org/IfIsEvil Feb 20, 2012 at 12:01
  • 1
    Yeah, I undersrtand this. Still, I have examples, where if is a lot better and solved tons of problems in my opinion. Also, I did not recommend the problematic, quoted types of use :) Feb 20, 2012 at 13:46
  • 1
    And still, testing $uri inside location is really evil -- this is exactly what location is for. Feb 20, 2012 at 17:38
  • 1
    Could you please give me a detailed explanation why exactly? I still see this is the most elegant way to solve this exact problem. Feb 21, 2012 at 8:27
  • 1
    location directive is used to define a configuration based on URI: wiki.nginx.org/HttpCoreModule#location It is optimized for this task (i.e. static lookups are much faster than regexp matches), it has reasonable precedence rules. Basically I'm just re-iterating what documenation says. Feb 21, 2012 at 8:40

You must log in to answer this question.

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