前提
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