Nginx 重定向时获取域名的方法示例
TL;DR
如果你在处理Nginx重定向时要获取原请求的域名(比如HTTP到HTTPS),请用$host而不是$server_name。
问题和解决方案
今天碰到一个问题,服务器上一个子域名的请求重定向到另一个子域名上面去了。查了一段时间发现这个问题只有在HTTP到HTTPS跳转的时候才会发生。大概是这样:
从HTTP的sub2子域名跳转到HTTPS的sub1子域名
http://sub2.example.com/more_things->https://sub1.example.com/more_things
我用的Nginx,当初为了让HTTP请求跳转到同名的HTTPS请求,配置如下:
http{ server{ listen80; server_namesub1.example.comsub2.example.com; return301https://$server_name$request_uri; } server{ listen443sslspdy; server_namesub1.example.comsub2.example.com; #... } }
因为301是永久重定向,某些浏览器的缓存会记住重定向,下次访问原地址就会直接向新地址发请求,所以这个问题在浏览器里面不一定重现得了(包括Chrome的IncognitoWindow),能每次完整重现的方式只有curl。
$curl-Ihttp://sub2.example.com/ HTTP/1.1301MovedPermanently Server:nginx/1.9.3(Ubuntu) Date:Tue,23Feb201606:06:30GMT Content-Type:text/html Content-Length:193 Connection:keep-alive Location:https://sub1.example.com/
查了一下,发现问题出在$server_name变量上。这个变量会始终返回server_name中第一个名字。这里其实应该用$host变量。修改后的配置如下:
http{ server{ listen80; server_namesub1.example.comsub2.example.com; return301https://$host$request_uri; } }
$host变量会按照以下优先级获取域名:
- Request-Line中的域名信息。Request-Line包含method,uri和HTTP版本。
- 请求头信息中的"Host"。
- Nginx中匹配的server_name配置。
这几乎可以保证在任何环境下正确地得到域名。如果是同域名下的重定向最好都用$host。
参考资料
NginxWiki-$host
Nginx官方文档。其中对$host讲的比较详细,但$server_name只是一笔带过。
StackOverflow-WhatisthedifferencebetweenNginxvariables$host,$http_host,and$server_name?
StackOverflow上关于三个变量区别的讨论。里面提到了为什么$host是适用于所有场景的唯一选择。
HTTP/1.1:Request-Line
HTTP/1.1规范中对Request-Line的描述。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。