I want a request to http://example.com/foobar to return http://example.com/foobar.jpg. (Or .gif, .html, .whatever)

This is trivial to do with Apache MultiViews, and it seems like it would be equally easy in Nginx. This question seems to imply that it'd be easy as try_files $uri $uri/ index.php; in the location block, but that doesn't work.

try_files $uri $uri/ =404; doesn't work, nor does try_files $uri =404; or try_files $uri.* =404; Moving it between my location / { block and the regexp which matches images has no effect.

Crucially, try_files $uri.jpg =404; does work, but only for .jpg files, and it throws a configuration error if I use more than one try_files rule in a location block!

The current server { block:

server {
        listen   80;
        server_name     example.org www.example.org;
        access_log  /var/log/nginx/vhosts.access.log;
        root   /srv/www/vhosts/example;
        location / {
                root   /srv/www/vhosts/example;

        location ~* \.(?:ico|css|js|gif|jpe?g|es|png)$ {
                expires max;
                add_header Cache-Control public;
                try_files $uri =404;

Nginx version is 1.1.14.

  • You should be able to simply list the files to try in order: try_files $uri.jpg $uri.gif $uri.png $uri.css $uri.js $uri/ =404. – cyberx86 Apr 7 '12 at 1:35

You can emulate Apache's MultiViews, by passing the various filenames to try to try_files.

Nginx's try_files directive does exactly what the name suggests - it tries files in the order the are specified, and if not found, will move to the next file. Typically, the last entry is a fallback that is guaranteed to work - either a named location block, or an error page.

The commonly seen parameters of try_files: $uri and $uri/ really are the paths passed to nginx - with and without the trailing slash.

So, if you go to example.com/path/to/myfile

$uri = /path/to/myfile
$uri/ = /path/to/myfile/

With the try_files $uri $uri/ directive, nginx will try exactly what is passed ($uri) - and if that file exists, will serve it, otherwise will try to find a matching directory ($uri/) and serve that (using whatever index you have specified).

Since the files you are trying to serve don't actually match the path in $uri, you need to append the extension to $uri for it to work:

$uri.jpg will match (from the above example) myfile.jpg - hence why only JPEGs worked when you used it.

Since you can specify multiple files to try in try_files, having more than one try_files directive doesn't really make sense - which is why it is not allowed.

In its simplest form, therefore, just list the files you want, in the order you wish to try them (e.g.):

try_files $uri.jpg $uri.gif $uri.png $uri.css $uri.js $uri/ =404

The second location block is interesting in this case. Typically, nginx will only ever process one location block - the one that matches best. However, in the case of rewrite ... last processing will restart and check all available location blocks. This is essentially what try_files amounts to - check if exists and rewrite ... last, the key difference being the absence of the arguments passed which are stripped by try_files unless explicitly added (e.g. with $uri?$args).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.