nginx – How to Build a Nginx Location Wildcard to Match /sub/test.jpg but Not /test.jpg

nginx

I have a location rule in nginx which tries to catch any js, css and jpg files:

server{
    listen 80;
    server_name example.com

    location ~* \.(js|css|jpg)$ {
        root /srv/html;
    }
}

This works fine. When I hit http://example.com/test.jpg it loads my image, so the permissions are correct.

However I want to change this so that only items under http://example.com/sub/ are matched.

So, based on this answer I changed the location to:

location ~* ^/sub/\.(js|css|jpg)$ {
    root /srv/html;
}

but this location doesn't appear to match http://example.com/sub/test.jpg

I also tried with:

location ~* ^/sub/.+\.(js|css|jpg)$ {
    root /srv/html;
}

which matches the location block, but looks for the file in /srv/html/sub/ according to my error log:

open() "/srv/html/sub/test.jpg" failed (2: No such file or directory)

What's the correct way to write this so that I can:

  • access http://example.com/sub/test.jpg
  • nginx retreives the file from /srv/html/test.jpg (which also works for *.jpg, *.css and *.js)
  • the rule doesn't match http://example.com/test.jpg

Best Answer

You have a file located at /srv/html/test.jpg and you want to access it using the URI /sub/test.jpg.

This requires the alias directive as the path to the file cannot be constructed by simply concatenating the document root with the URI.

For example:

location /sub/ {
    alias /srv/html/;
}

The trailing / on both the location and alias values is significant. Either both have a trailing / or neither have a trailing /.


Using the alias directive with a regular expression location block, requires you to capture the remainder of the URI and construct the path to the file in the alias statement.

For example:

location ~* ^/sub(/.+\.(js|css|jpg))$ {
    alias /srv/html$1;
}

The order of the regular expression location blocks is significant. The regular expressions are evaluated in order, so a more specific regular expression should be placed before a less specific regular expression.

See this document for the alias directive, and this document for the location directive.