DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

Nginx 静态页不存在时返回 500:try_files 缺少终止处理

静态站点未命中路径后发生内部跳转循环,核对 try_files 最后一项,按静态页面或应用入口选择终止方式。

静态站点已有文件能访问,不存在的路径却报 rewrite or internal redirection cycle,最终返回 500。如果配置只有 try_files $uri $uri/;,先检查最后一个参数的含义,而不是添加更多 rewrite。

这里讨论 Nginx 自己提供静态文件的场景。PHP 前端控制器和单页应用需要自己的回退入口,不能直接把所有路由改成 404。

最后一个参数不是普通的文件检查

下面是容易误读的示例:

location / {
    try_files $uri $uri/;
}

try_files 会依次检查最后一个参数之前的候选文件。它最后一项是未命中时的处理目标,可以是内部跳转 URI、命名 location,或者 =404 这样的状态码。

因此,以上配置里的 $uri/ 位于最后,并没有成为一个普通的目录检查项。文件不存在时,请求会内部跳到这个 URI,再次匹配 location;如果仍走相同的处理路径,就可能形成循环。Nginx 限制内部跳转次数,达到限制后返回 500。

检查日志中循环指向的路径,并对照实际命中的 root、alias、try_files、index 和 error_page。若日志指向 /index.html,则可能是另一种情况:回退首页不存在或不可访问,内部跳转又回到了同一条回退规则。相同报错不代表每次都只缺少 =404。

纯静态站点,明确以 404 结束

如果未找到文件和目录时就应该返回不存在,可以写成下面的结构。/srv/www/site 是示例根目录,需要替换:

server {
    listen 80;
    server_name example.com;
    root /srv/www/site;
    index index.html;

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

这里 $uri/ 才是目录存在性检查,=404 则结束未命中的请求。保留原配置,检查通过后重载实际服务实例;出现异常时恢复原文件并再次检查、重载。默认配置检查示例是:

nginx -t

配置检查能发现语法错误,但不会遍历所有请求路径。因此,重载后仍要分别检查一个已有静态文件和一个确定不存在的路径。

回退到应用时,确认入口能结束请求

单页应用可能需要不存在的页面路由回退到 /index.html;PHP 应用可能需要交给 /index.php。这两种场景应保留应用要求的回退机制,并确认入口文件真实存在、访问权限正确,且不会再次落回同一条不存在文件规则。

如果只有某个扩展名的请求循环,还要检查它是否被另一条正则 location 抢先处理。不要把静态站点的 404 方案整段覆盖到已有 PHP 或代理配置上。

自定义 404 页面也要有正确的文件路径。修复 try_files 后,如果错误从 500 变成正确的 404,但自定义页面未显示,应再查 error_page 的内部目标;不要为了展示错误页把 404 改成 200。

最终应看到:已有资源正常返回,不存在的资源返回预期的 404,应用路由仍按原设计工作,日志中不再出现内部跳转循环。只验证首页不能覆盖这个故障。