nginx中tryfiles引起301重定向
背景
公司官网项目,通过两层 nginx 请求数据,发现重定向后地址带上了端口,如:https://wwww.kch8.top:18000/test?name=huang
项目架构
第一层 nginx
第一层通过代理转发到第二层
1 | server |
第二层 nginx
第二层是 vue 项目,采用 history 模式,故用 try_files 解决浏览器刷新 404 问题
1 | server |
问题分析
301 问题
第一层只做转发,一般没有问题;往下排查,第二层可能性最大;try_files 引起的一次重定向
try_files 说明
try_files 指令后面可带多个 uri,进行多次匹配,直到找到相关资源为止。
针对上面try_files $uri $uri/ /index.html
,
请求的 url 为:https://www.kch8.top/product/detail?productId=100000
,
站点部署结构为:
1 | . |
上述请求 uri 为/product/detail
,根据 try_files 配置,匹配如下:
a. $uri
进行匹配,资源文件不存在;
b. 向下$uri/
匹配,发现 detail 文件夹存在,则返回 301 地址https://www.kch8.top/product/detail/?productId=100000
(detail 文件下存在默认 index.html 文件,并没有匹配 index.html 内容,这和 location 下 uri 匹配有区别)
c. b 步骤不匹配,则找根目录下 index.html,最后这个 uri 一定要存在,否则会报 404 错误;(最后这个匹配是内部重定向,而不是下发 301 或 302 这种)
重定向带端口问题
这个问题是由 try_files 产生了一次重定向,生成的 url 为https://www.kch8.top:8081/product/detail/?productId=100000
url 中域名是通过 server_name 获取;
url 中端口是通过 listen 获取;
解决方案
301 问题
根据站点,根目录文件层级,try_files 做出如下修改:
1 | try_files $uri $uri/index.html /index.html |
对第二个 uri,直接找目录下的 index.html 文件
重定向带端口问题
重定向 url 中的域名,可以通过server_name_in_redirect
控制,默认开启,官方解释:
1 | Enables or disables the use of the primary server name, specified by the server_name directive, in absolute redirects issued by nginx. When the use of the primary server name is disabled, the name from the “Host” request header field is used. If this field is not present, the IP address of the server is used. |
重定向 url 中的端口,可以通过port_in_redirect
控制,默认开启,官方解释:
1 | Enables or disables specifying the port in absolute redirects issued by nginx. |
关闭绝对重定向,可以通过absolute_redirect
控制,默认开启,官方解释:
1 | If disabled, redirects issued by nginx will be relative. |
故将absolute_redirect
设置为off,改为相对重定向,避免出现端口问题
参考资料
nginx中tryfiles引起301重定向