这是配置:
index index.html;
location / {
try_files $uri $uri/ = 404;
}
我在 http://localhost/path/a/ 发出请求。我假设这是 URI,因此在 $uri 阶段,try_files 将查看 /path/a/ 并提供 index.html(如果有)。
我从文档中读到这一点,It is possible to check directory’s existence by specifying a slash at the end of a name, e.g. “$uri/”.
但这对我来说没有任何意义。
答案1
正是这个$uri/
部分使得 nginx 假设 URI 可以是目录名并在其中寻找索引文件的存在。
假设目录结构如下:
/var/www/html
├── a
│ └── index.html
├── b
│ ├── index.html
│ └── index.htm
├── c
│ └── test.html
...
以及以下 nginx 配置:
server {
root /var/www/html;
index index.htm index.html;
location / {
try_files $uri $uri/ =404;
}
}
以下是以下curl
请求发生的情况:
-
curl http://localhost/a
返回重定向:
HTTP/1.1 301 Moved Permanently Location: http://localhost/a/
-
curl http://localhost/a/
返回
/var/www/html/a/index.html
文件内容。 -
curl http://localhost/b
返回重定向:
HTTP/1.1 301 Moved Permanently Location: http://localhost/b/
-
curl http://localhost/b/
返回
/var/www/html/b/index.htm
文件内容(按照使用指令指定的顺序检查索引文件的存在index
)。 -
curl http://localhost/c
返回重定向:
HTTP/1.1 301 Moved Permanently Location: http://localhost/c/
-
curl http://localhost/c/
由于目录中没有索引文件
/var/www/html/c/
,除非您的配置中有一个指令(在这种情况下 nginx 将返回目录列表),否则curl
命令将返回。HTTP 403 Forbidden
autoindex on;
/var/www/html/c/
如果你的 nginx 配置如下
server {
root /var/www/html;
index index.htm index.html;
location / {
try_files $uri =404;
}
}
现在,上述每个请求都将返回HTTP 404 Not Found
错误。autoindex
如果存在指令,则不会产生任何效果。获取index.html
内容的唯一方法是明确指定它,例如等http://localhost/a/index.html
。http://localhost/b/index.htm
非常重要但绝对不明显的一点是,index
与 一起使用的指令try_files $uri $uri/ =404
可能会导致内部重定向。例如,如果您有以下配置:
server {
root /var/www/html;
index index.htm index.html;
location / {
add_header X-Test test1;
try_files $uri $uri/ =404;
}
location /a/index.html {
add_header X-Test test2;
}
}
请求将导致从到 的http://localhost/a/
内部重定向,并返回将自定义标头设置为 的文件内容,而不是!/a/
/a/index.html
/var/www/html/a/index.html
X-Test
test2
test1
最后值得一提的是,这try_files $uri $uri/ =404;
是默认的 nginx 行为,因此
location / {
try_files $uri $uri/ =404;
}
和
location / {}
位置完全相同。
更新
OP 的另一个问题:
我的想法是:
$uri
检查 URI 本身,并将$uri/
URI 作为查找索引文件的目录进行检查。对于http://localhost/a
使用,try_files $uri /file.html =404;
我得到了file.html
。现在很好!对于http://localhost/a
使用,try_files $uri/ /file.html =404;
我file.html
也得到了 。为什么?我期望index.html
。此外,try_files $uri $uri/ /file.html =404;
将为我提供index.html
。
真是个好问题!如果不回答这个问题,整个答案就会不完整。让我们看看这里发生了什么。
在您的 nginx 配置中拥有http://localhost/a/
请求和try_files $uri/ /file.html =404;
指令后,nginx 第一步检查/var/www/html/a/
目录是否为目录,接下来检查是否存在索引文件,发现其中有一个文件,并从到index.html
进行内部重定向。第二步,在同一个位置块内,nginx 检查是否为目录,但不是!而且由于您没有将组件作为指令参数,因此它会进行下一步文件检查,找到它并返回其内容。/a/
/a/index.html
/var/www/html/a/index.html
$uri
try_files
/var/www/html/file.html
因此,您可能会认为使用try_files
不带$uri
参数的指令完全没用。通常情况下确实如此,但在某些情况下也可以这样做,例如当您想要隐藏内部站点结构时。以下是示例:
server {
root /var/www/html;
index index.html;
location / {
try_files $uri/ =404;
}
location ~ /index\.html$ {
internal; # only accessible via internal URI rewrite
try_files $uri =404;
}
location ~ \.(js|css|jpe?g|png)$ {
# serve the assets in a usual way
try_files $uri =404;
}
}
使其成为内部请求后,您将无法通过类似这样的请求location ~ /index\.html$ { ... }
直接访问您的文件(将返回一个)。但是,由于内部 URI 重写指令与一个指令一起使用,类似这样的请求仍然可行。index.html
http://localhost/a/index.html
HTTP 404 Not Found
http://localhost/a/
index
try_files $uri/ =404