Why nginx returns 301 status code when trying to open a directory?
I am trying to understand how Nginx works. Now I'm working on index
and try_files
directives. My config file is this:
events {}
http {
rewrite_log on;
error_log /var/log/nginx/localhost.error_log debug;
server {
root /app;
listen 8080;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
}
Also /app/
tree directory is:
/app
|-- abcd.html
|-- file.php
|-- index.html
|-- index.php
|-- sss
| `-- index.html
|-- style.css
`-- thumb.png
When I try to open localhost:8080
everything works as expected. It first uses location /
context. Then uses $uri/
to read the root directory. Then because index file name has been specified, it uses index file in that directory. Also, the log file can show that:
...
2021/10/27 11:37:49 [debug] 1297#1297: *1 test location: "/"
2021/10/27 11:37:49 [debug] 1297#1297: *1 using configuration "/"
...
2021/10/27 11:37:49 [debug] 1297#1297: *1 generic phase: 12
2021/10/27 11:37:49 [debug] 1297#1297: *1 try files handler
2021/10/27 11:37:49 [debug] 1297#1297: *1 http script var: "/"
2021/10/27 11:37:49 [debug] 1297#1297: *1 trying to use file: "/" "/app/"
2021/10/27 11:37:49 [debug] 1297#1297: *1 http script var: "/"
2021/10/27 11:37:49 [debug] 1297#1297: *1 trying to use dir: "/" "/app/"
2021/10/27 11:37:49 [debug] 1297#1297: *1 try file uri: "/"
2021/10/27 11:37:49 [debug] 1297#1297: *1 generic phase: 13
2021/10/27 11:37:49 [debug] 1297#1297: *1 content phase: 14
2021/10/27 11:37:49 [debug] 1297#1297: *1 open index "/app/index.html"
2021/10/27 11:37:49 [debug] 1297#1297: *1 internal redirect: "/index.html?"
...
But when I open localhost:8080/sss
, It first responds with a redirection to localhost:8080/sss/
, then opens the index file inside the sss/
directory. Here is the logs:
2021/10/27 11:46:07 [debug] 1297#1297: *3 test location: "/"
2021/10/27 11:46:07 [debug] 1297#1297: *3 using configuration "/"
2021/10/27 11:46:07 [debug] 1297#1297: *3 http cl:-1 max:1048576
2021/10/27 11:46:07 [debug] 1297#1297: *3 rewrite phase: 3
2021/10/27 11:46:07 [debug] 1297#1297: *3 post rewrite phase: 4
2021/10/27 11:46:07 [debug] 1297#1297: *3 generic phase: 5
...
2021/10/27 11:46:07 [debug] 1297#1297: *3 try files handler
2021/10/27 11:46:07 [debug] 1297#1297: *3 http script var: "/sss"
2021/10/27 11:46:07 [debug] 1297#1297: *3 trying to use file: "/sss" "/app/sss"
2021/10/27 11:46:07 [debug] 1297#1297: *3 http script var: "/sss"
2021/10/27 11:46:07 [debug] 1297#1297: *3 trying to use dir: "/sss" "/app/sss"
2021/10/27 11:46:07 [debug] 1297#1297: *3 try file uri: "/sss"
2021/10/27 11:46:07 [debug] 1297#1297: *3 generic phase: 13
2021/10/27 11:46:07 [debug] 1297#1297: *3 content phase: 14
...
2021/10/27 11:46:07 [debug] 1297#1297: *3 content phase: 18
2021/10/27 11:46:07 [debug] 1297#1297: *3 http filename: "/app/sss"
2021/10/27 11:46:07 [debug] 1297#1297: *3 add cleanup: 000055AA4A146290
2021/10/27 11:46:07 [debug] 1297#1297: *3 http static fd: -1
2021/10/27 11:46:07 [debug] 1297#1297: *3 http dir
2021/10/27 11:46:07 [debug] 1297#1297: *3 http finalize request: 301, "/sss?" a:1, c:1
2021/10/27 11:46:07 [debug] 1297#1297: *3 http special response: 301, "/sss?"
2021/10/27 11:46:07 [debug] 1297#1297: *3 http set discard body
...
Why it didn't respond with the index file inside the sss/
directory, just like the root directory, without external redirection?
Solution 1:
The $uri/
term on a try_files
statement works the same way as Nginx default behaviour.
If you provide a URI without a trailing /
that points to a directory, Nginx will first append a trailing /
using an external redirect (i.e. 301
).
If you provide a URI with a trailing /
that points to a directory, the index
directive will be invoked and may generate an internal redirect to whichever file is specified (e.g. index.html
).
Although the documentation is clear that a trailing /
is required by the index
directive. I cannot find where the former behaviour is documented.