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.
Best Answer
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
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 onetry_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.):
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 whattry_files
amounts to - check if exists andrewrite ... last
, the key difference being the absence of the arguments passed which are stripped bytry_files
unless explicitly added (e.g. with$uri?$args
).