在 nginx 中,`try_files` 配合 `autoindex on` 实现目录列表兜底的核心做法是:将 `try_files` 的最后一个参数指向一个内部重定向(internal redirect),该重定向触发带有 `autoindex on` 的 location 块。具体而言,使用 `try_files $uri $uri/ @fallback;` 并在 `@fallback` 中开启自动索引,这样当请求的文件或目录不存在时,nginx 会进入 fallback 逻辑并返回目录内容。

try_files 如何触发目录列表
要实现这一功能,需要在 location 块中配置 try_files 指令,并将最后一步指向一个命名位置(Named Location)。这个命名位置必须包含 autoindex on 指令。当 $uri 对应的文件不存在,且 $uri/ 对应的目录也不存在时,Nginx 会将请求内部转发到该命名位置,从而激活目录列表功能。

server {
listen 80;
server_name example.com;
root /var/www/html;
# 主 location 处理静态资源
location /files/ {
# 尝试匹配文件,再尝试匹配目录,最后跳转到 fallback
try_files $uri $uri/ @dir_list;
}
# 命名位置:用于兜底显示目录列表
location @dir_list {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
# 重新解析 URI 以获取正确的根路径
alias /var/www/html/;
}
}
上述配置中,/files/ 是主要访问路径。try_files 首先检查是否存在与请求 URI 完全匹配的文件($uri)。如果不存在,则检查是否存在同名目录($uri/)。如果两者都不存在,请求将被内部重定向到 @dir_list。在 @dir_list 中,alias 指令确保目录列表显示的是正确的物理路径内容,而 autoindex on 则告诉 Nginx 生成 HTML 格式的目录索引。
如何处理子目录和权限控制
在实际部署中,可能需要对不同的子目录应用不同的目录列表策略,或者限制某些敏感目录的访问。可以通过嵌套 location 块或使用正则表达式来细化控制。例如,可以为特定前缀启用自动索引,而为其他前缀禁用它。

server {
listen 80;
server_name example.com;
root /var/www/html;
# 全局默认不显示目录列表
location / {
autoindex off;
try_files $uri $uri/ =404;
}
# 特定目录启用目录列表
location /public/ {
autoindex on;
autoindex_exact_size off;
try_files $uri $uri/ @public_dir;
}
location @public_dir {
alias /var/www/html/public/;
autoindex on;
}
# 敏感目录禁止访问
location /private/ {
deny all;
}
}
在这个例子中,/ 位置块设置了默认的 autoindex off,并使用 =404 作为 try_files 的最后一步,确保未找到的资源返回 404 错误而不是目录列表。对于 /public/ 目录,我们启用了 autoindex on 并配置了相应的 try_files 和命名位置。而对于 /private/ 目录,我们直接使用 deny all 禁止所有访问,确保安全。这种结构允许在同一服务器块中灵活管理不同目录的访问策略。
基于 try_files 中 $uri/ 匹配失败的具体问题
当 try_files 中的 $uri/ 匹配失败时,意味着请求的路径既不是文件也不是现有目录。此时,Nginx 会继续执行 try_files 列表中的下一个选项。如果下一个选项是一个命名位置(如 @dir_list),则请求会被内部重定向到该位置。关键在于,命名位置中的 alias 或 root 必须正确设置,以确保目录列表显示的是预期的内容。如果 alias 设置错误,可能会导致目录列表显示空内容或错误的路径。











