双层 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重定向处理过程分析

简单数据结构路径描述语法

适用于 JSON 结构的 path 描述语法,用字符串形式便捷描述指定数据位置。

简单类型

基本的路径描述语法。

数值类型

字面量,如:
0
1
-1

字符串类型

字面量,可选双引号,如:
string
"string"

布尔类型

字面量,如:
true
false

对象类型

点号分割,可选双引号,如:
object.key
object."key"

数组类型

中括号分割,可选数值索引或对象索引,如:
[]
[0]
[-1]
[{key:value}]
[{"key":"value"}]

组合类型

多种路径描述语法组合使用。

多层对象

多个对象类型组合,如:
object.key
object.key.key

多维数组

多个数组类型组合,如:
[][]
[0][]
[][0]
[0][0]
[{key:value}][0]
[0][{key:value}]
[{key:value}][{key:value}]

对象和数组

对象和数组组合,如:
object.key[]
object.key[].key
object.key[{key:value}]
object.key[{key:value}].key
[].key
[{key:value}].key

(扩展)运算符

基本的数据运算语法,可选小括号。

算术运算符

+ - * / % 如:
(0 + 1 - 2) * 3 / 4 % 5
"string" + "string"

比较运算符

== != > >= < <= 如:
object.key == object.key

逻辑运算符

&& || ! 如:
object.key && object.key

位运算符

& | ~ ^ << >> 如:
object.key & object.key

Markdown