5
votes

I have a example web server with only one index.html file in a www directory. I can setup a nginx with following configuration:

location /subfolder {
     alias /data/www;
     try_files $uri $uri/ /index.html;
}

In browser I can see correct response on my local domain test.local/subfolder, also test.local/subfolder/something returns a default nginx page (it is normal because root is not set)

if I change a configuration to

location /subfolder {
     alias /data/www;
     try_files $uri $uri/ /index.html =404;
}

response to test.local/subfolder is still correct, but test.local/subfolder/something and all URI with /subfolder prefix return a index.html of correct response also status is 200 not 404. If I remove /index from try_files I get the same result

I wonder how nginx process request with =404 fallback, but cant find any information, not even in a official docs.

UDAPTE:

I found out that a alias directive should end with an / but still dont get a =404 functionality and purpose because a status is still 200ok

2

2 Answers

9
votes

The try_files directive only supports these syntaxes:

try_files file ... uri;
try_files file ... =code;

It doesn't support:

try_files file ... uri =code;

The difference between file and uri here, is that for file arguments, NGINX will check their existence before moving on to next argument; for uri, it won't.

If the last argument has form of a =code, then all prior arguments to it are files (checked for existence).

From this, you can get a conclusion that with request URI /foo/bar and this config:

root /var/www;
location /foo/ {
  try_files $uri $uri/ =404;
}

... Will not trigger 404 error if any of the files exist:

  • /var/www/foo/bar
  • /var/www/foo/bar/ directory (if you have autoindex enabled)
  • /var/www/foo/bar/index.html (or index.php, etc.) (due to value of index)

Only when none of the above exist, NGINX will trigger 404 error.

7
votes

You should define the root of your server, then the default indexes and then add the =404 to try_files:

server {
  server_name example.com;
  root /var/www/html/example.com;
  index index.html index.htm index.php;
  # This is optional - if you want a customized 404 error page
  error_page 404 /404.html;

  location /subfolder {
    try_files $uri $uri/ =404;
  }
}

The difference between root and alias is that root appends location to get the absolute path in the filesystem while alias excludes the location. So for example when you try to fetch http://example.com/subfolder/filename.txt

server_name example.com;
root /var/www/html/example;

location /subfolder {
  try_files $uri $uri/ =404;
}

will return the contents of /var/www/html/example/subfolder/filename.txt (if it exists) while

server_name example.com;

location /subfolder {
  alias /var/log;
  try_files $uri $uri/ =404;
}

will return the contents of /var/log/filename.txt (if it exists)