双层 nginx 转发下的 try_files 指令 301 返回错误的 location 地址

背景信息:
使用 http://example.com/path 地址,访问服务器 path 目录下的 index.html 文件。
在单层 nginx 下,被 301 到 http://example.com/path/ 地址,可正常访问。
在双层 nginx 下,被 301 到 http://example.com:1234/path/ 地址,会访问失败。
根据环境不同,被 301 返回的地址, 协议/域名/IP/端口 等,都可能不同。

nginx 配置:

配置说明:
1. 检查 path 文件是否存在,存在则响应文件内容。
2. 检查 path/ 目录是否存在,存在则响应 301 跳转至 path/ 地址。
2.1 在新的请求中,检查 path/ 目录是否存在,存在则检查 path/index.html 文件是否存在,存在则响应文件内容。
3. 检查 /index.html 文件是否在,存在则响应文件内容。
4. 响应 404 状态码。

问题解析:
在单层 nginx 下,响应的 协议/域名/IP/端口 等,与请求一致。
在双层 nginx 下,当第一层 nginx 修改 协议/域名/IP/端口 后,转发至第二层 nginx 处理。
第二层 nginx 响应的 301 跳转地址,是基于被修改后的请求的,而第一层 nginx 不会修改这个 301 响应,原样输出到客户端后,造成访问失败。

解决方案:
最简单的方案:修改 absolute_redirect 指令为 off ,但要小心相对 Location 的兼容性。
最合理的方案:修改访问 http://example.com/path 地址为直接访问 http://example.com/path/ 地址,避免触发 301 跳转,减少一次网络请求。
有缺陷的方案:修改 try_files 指令内容为以下内容。但会造成 html 页面中用 相对路径 引用的静态资源失效。

参考资料:
try_files
absolute_redirect
server_name_in_redirect
port_in_redirect
nginx-causes-301-redirect-if-theres-no-trailing-slash
how-to-stop-nginx-301-auto-redirect-when-trailing-slash-is-not-in-uri
Nginx的301重定向处理过程分析

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注