Dmitry Dmitriy
Dmitry Dmitriy

Reputation: 93

Why try_files directive missing slash between root and filename?

I'm trying to set up Nginx to work as reverse proxy, but also handle single static page (greeting) by its own:

root /usr/share/project/;
location = / {
    try_files index.html =404;
}

This config always return 404. When I tried to figure out what exactly happens I rewrite try_files directive to make it fail:

try_files index.html index.html;

And was surprised at what I saw in the error.log:

2019/05/07 17:30:39 [error] 9393#9393: *1 open() "/usr/share/projectindex.html" failed (2: No such file or directory), client: 10.25.88.214, server: , request: "GET /index.html HTTP/1.1"

As you can see result file name is projectindex.html. Slash was missed. I'm trying to add / and ./ in different places but it did not lead to anything.

Finally I replace my config by following:

root /usr/share/project/;
location = / {
    try_files /index.html =404;
}
location = /index.html {
}

and it works.

I do not understand what is wrong with the first config. And also I do not understand the meaning of an empty location:

location = /index.html {
}

and why it works properly.

Maybe there is a better way to do the same?

Upvotes: 4

Views: 653

Answers (1)

Richard Smith
Richard Smith

Reputation: 49692

root can optionally take a trailing / - it doesn't matter and it is ignored.

The file elements of a try_files statement (as with all URIs in Nginx) require a leading /. See this document for details.

For example:

root /usr/share/project;
location = / {
    try_files /index.html =404;
}
location / {
    proxy_pass ...;
}

This works because the URI is internally rewritten to /index.html and processed within the same location.


If you use the index directive, the URI is internally rewritten to /index.html and Nginx will search of a matching location to process the request. In this case, you need another location to process the request.

For example:

root /usr/share/project;
location = / {
    index index.html;
}
location = /index.html {
}
location / {
    proxy_pass ...;
}

The empty location block inherits the value of root from the outer block. The index statement is the default value anyway, so strictly speaking, you do not need to specify that statement either. Notice that the values of the index directive do not require a leading /. See this document for details.

Upvotes: 2

Related Questions