一般项目上常用Nginx做负载均衡和静态资源服务器,本案例中项目上使用Nginx作为静态资源服务器出现了很奇怪的现象,我们一起来看看。
“诡异”的现象
部署架构如下图,Nginx作为静态资源服务器监听8080端口,客户浏览器通过API网关的443端口(就是https)获取Nginx静态资源。
现象是用户浏览器访问WAF的https地址后,WAF将请求SSL解密再请求Nginx 8080
端口的/categories
路径,但返回给客户端的却是 https://www.yihuo.tech:8080/categories/
!!! 这还是个重定向响应,响应头里包含 Location: https://www.yihuo.tech:8080/categories/
,由于API网关并没有开放这个端口号,所以请求到这里就无法继续下去了。
问题分析
后来根据浏览器F12打开调试窗口的network看到原来如此
这里就很明确是Nginx返回的301永久重定向,Nginx使用自己端口号暴露出来做的重定向。到此问题已清晰,只要不让Nginx把端口号暴露出来就可以了。
问题原因
这得先从Nginx的处理流程说起。
案例中,我们请求的是 https://API网关/categories
,Nginx收到请求发现 /categories
是一个目录,就会设置响应头Location
和空的响应体,试图让浏览器以目录方式访问资源。而浏览器收到响应后,解析响应头发现 Location
响应头确定要重定向,就开始跳转 https://WAF/categories/
。
以上是正确合理的情况,不合理的点在于:Nginx为啥把自己端口号暴露出来了?
经过查询了Nginx官方文档,发现了三个有联系的配置项,分别贴图出来:
这三个配置分别是 absolute_redirect / server_name_in_redirect / port_in_redirect,以下简要说明下三者作用:
absolute_redirect
:启用时表示绝对路径重定向,默认on
启用server_name_in_redirect
: 启用时表示使用Nginx的server_name
配置替换重定向路径,默认off
禁用port_in_redirect
:启动时表示重定向时替换重定向的端口号,默认on
启用
这三个配置关系中,如果absolute_redirect
配置off
,则后两个配置失效。
解决方案
至此,可以有两种解决方案,根据实际情况任选其一即可:
absolute_redirect
配置off
(禁用绝对路径跳转,相当于自动识别目录)port_in_redirect
配置off
(禁止替换重定向端口号)
这两个方案的配置位置可以是http / server / localtion
块,作用范围也是根据配置位置决定的。
至于本案例中,由于多个项目使用同一个server
,就在location
块中添加了 port_in_redirect off;
解决了问题。
总结
本文试图从问题现象到分析与解决方案的提出让读者能对Nginx的301重定向做到心中有数,相信读者看完本文再出现类似的问题解决起来肯定更轻松愉快!