前提
Nginx配置了stream的TCP流量转发,将myhosthost
域名443
端口的流量,转发到10240
# 流量转发核心配置 stream { # 这里就是 SNI 识别,将域名映射成一个配置名 map $ssl_preread_server_name $backend_name { myhosthost web; # 域名都不匹配情况下的默认值 default web; } # web,配置转发详情 upstream web { server 127.0.0.1:10240; } # 监听 443 并开启 ssl_preread server { listen 443 reuseport; listen [::]:443 reuseport; proxy_pass $backend_name; ssl_preread on; } }
http服务器:
server { listen 10240 ssl; server_name myhosthost; ssl_certificate cert/myhosthost.pem; ssl_certificate_key cert/myhosthost.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location /product { root /www; index index.html; } }
现象
访问https://myhosthost/product
的时候,会被重定向到https://myhosthost:10240/product/
导致无法加载,直接访问https://myhosthost/product/
可以访问。
我们期望的是访问https://myhosthost/product
的时候,重定向到https://myhosthost/product/
知识点
首先对比说明Nginx以下两个现象:
1. 访问的uri最后带斜杠
http://localhost/product/ >>>> 查找 product下的index页面,存在就返回;不存在且未开启自动索引目录选项(指令是:autoindex on),则报403错误
2. 访问的uri最后不带斜杠
http://localhost/product >>>> 查找product文件,存在就返回;若存在product的文件夹,会产生301跳转,且自动将uri补全为http://localhost/product/ ,跳转的域名由server_name_in_redirect 指令控制,跳转的端口由port_in_redirect控制
server_name_in_redirect
1. server_name_in_redirect on
,URL 重定向为: server_name 中的第一个域名 + 目录名 + /;例如 配置文件中 server_name www.baidu.com; 则http://localhost/product 时会重定向到http://www.baidu.com/product/
2. server_name_in_redirect off
(默认值)URL 重定向为: 原 URL 中的域名 + 目录名 + /。
port_in_redirect
通过指定port_in_redirect off
告知nginx在redirect的时候不要带上port,使用原port,如果没有配置,默认该值为true
本文现象的原因
product是个目录,所以https://myhosthost/product
时本来会重定向到https://myhosthost/product/
,又因为stream中将443重定向到10240,server中listen 10240,所以最终重定向到了https://myhosthost:10240/product/
所以只需要在http、server、location
的任一节点中,添加port_in_redirect off
,就可以让其正确重定向到https://myhosthost/product/
参考文献
http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name_in_redirect
http://nginx.org/en/docs/http/ngx_http_core_module.html#port_in_redirect
https://segmentfault.com/a/1190000012778932