Using nginx try_files with multiple directory trees

I'd like to have nginx handle requests to a specific directory by checking to see if that path/file exists in several separate directories. For example, if my directory root had the following:

images/siteA/foo.jpg
images/siteB/b/bar.jpg
images/siteC/example.jpg

I'd like http://example.com/images/foo.jpg to return the file foo.jpg, http://example.com/b/bar.jpg to return the file bar.jpg and so fourth.

I've tried the following, but it just gets locked in redirect loops (and I don't want it to redirect, but actually serve the file to that URL):

  location /images/ {
    try_files /siteA/images/
              /siteB/images/
              /siteC/images/ =404;

  } 

I've also tried using capture groups like location ~/images/(.*)/ and adding $1 to the end of the URLs. I'm a little confused on the documentation and unsure how to accomplish this with nginx.


Solution 1:

You will need to use a regular expression location to capture the part of the URI following /images/. Then use try_files to test a series of URIs using each site prefix.

For example:

location ~ ^/images/(.*)$ {
    root /path/to/docroot/images;
    try_files /siteA/$1 /siteB/$1 /siteC/$1 =404;
}

You could inherit the value of root from the surrounding block, in which case adjust the parameters to try_files appropriately.

Solution 2:

As an alternative to the accepted answer you can use a named location (@my_path for example) to fallback in a other location, for example :

location / {
    root /etc/nginx/static;
    try_files $uri @index;
}

location @index {
    root /srv/http;
    try_files $uri $uri.html /index.html =404;
}