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 {
 listen  80;
 server_name sub1.example.com sub2.example.com;
 return  301 https://$server_name$request_uri;
 }

 server {
 listen  443 ssl spdy;
 server_name sub1.example.com sub2.example.com;
 # ...
 }
}

因为 301 是永久重定向,某些浏览器的缓存会记住重定向,下次访问原地址就会直接向新地址发请求,所以这个问题在浏览器里面不一定重现得了(包括 Chrome 的 Incognito Window),能每次完整重现的方式只有 curl 。

$ curl -I http://sub2.example.com/

HTTP/1.1 301 Moved Permanently
Server: nginx/1.9.3 (Ubuntu)
Date: Tue, 23 Feb 2016 06:06:30 GMT
Content-Type: text/html
Content-Length: 193
Connection: keep-alive
Location: https://sub1.example.com/

查了一下,发现问题出在 $server_name 变量上。这个变量会始终返回 server_name 中第一个名字。这里其实应该用 $host 变量。修改后的配置如下:

http {
 server {
 listen  80;
 server_name sub1.example.com sub2.example.com;
 return  301 https://$host$request_uri;
 }
}

$host 变量会按照以下优先级获取域名:

  1. Request-Line 中的域名信息。Request-Line 包含 method, uri 和 HTTP 版本。
  2. 请求头信息中的 "Host" 。
  3. Nginx 中匹配的 server_name 配置。

这几乎可以保证在任何环境下正确地得到域名。如果是同域名下的重定向最好都用 $host 。

参考资料

Nginx Wiki - $host
Nginx 官方文档。其中对 $host 讲的比较详细,但 $server_name 只是一笔带过。

StackOverflow - What is the difference between Nginx variables $host, $http_host, and $server_name?
StackOverflow 上关于三个变量区别的讨论。里面提到了为什么 $host 是适用于所有场景的唯一选择。

HTTP/1.1 : Request-Line
HTTP/1.1 规范中对 Request-Line 的描述。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Nginx下301重定向域名的方法小结

    linux中nginx 301重定向跳转方法总结,有需要的朋友可参考一下. 第一种情况:访问aaaaaaa站定向到bbbbbbbbbbb站 复制代码 代码如下: server { server_naaaaaaame www.aaaaaaa.com ; rewrite ^(.*) http://www.bbbbbbbbbbb.com$1 permaaaaaaanent; } 第二种情况:不是访问aaaaaaa站的全部重定向到指定页面 复制代码 代码如下: server { server_naaaa

  • nginx中域名、目录的301重定向配置示例

    301重定向不陌生, 有时候有需求把某目录整个重定向到一个二级域名,或者不带www的顶级域名请求全部重定向到带www的二级域名.如果是Apache,需要配置.htaccess,nginx不支持,需要在配置文件里面使用rewrite指令来实现. 顶级域名重定向到www 复制代码 代码如下: server {  server_name jb51.net;  rewrite ^/(.*)$ http://www.jb51.net/$1 permanent;  } 如上配置,所以jb51.net的请求都

  • Nginx 重定向时获取域名的方法示例

    TL;DR 如果你在处理 Nginx 重定向时要获取原请求的域名(比如 HTTP 到 HTTPS),请用 $host 而不是 $server_name . 问题和解决方案 今天碰到一个问题,服务器上一个子域名的请求重定向到另一个子域名上面去了.查了一段时间发现这个问题只有在 HTTP 到 HTTPS 跳转的时候才会发生.大概是这样: 从 HTTP 的 sub2 子域名跳转到 HTTPS 的 sub1 子域名 http://sub2.example.com/more_things -> https

  • 在nginx中设置三级域名的方法示例

    问题描述 通过配置nginx可以设置一个IP地址下面通过不同的端口访问不同的Web应用,但是时间长了之后端口号和应用之间的关系就很模糊了. 如 http://120.79.79.XX:9001 和foreign.XXX.xin 虽然这两个网址都是指向同一个网站,但是后者显然望文生义,比前者好很多.同时在网站SEO中,后者也比前者的权重更高. 基本知识 顶级域名:.com .cn 二级域名:baidu.com sina.com ,这其中baidu 和sina就是二级域名 三级域名:zhidao.b

  • nginx反向代理二级域名绑定方法及注意事项

    摘要 本文介绍了利用nginx实现多域名和多站点的绑定的方法及相关注意事项.您也可以只看标题或红色标注部分.☺ 1.应用场景 我们经常会遇到在同一台服务器建立多个Web站点的情况,普遍的做法是为不同的站点配置不同的端口,这样就可以用IP:Port的形式访问. 但是用IP访问毕竟不方便,不生动,不容易记忆.那么,我们可以给每个站点绑定不同的域名.(在这里我们仅谈公网情况)即使我们只有一个域名,我们可以设置多个二级域名,使用Nginx很容易实现. 2.基本要求 通常,网上教程会直接贴一段配置文件的代

  • nginx配置ssl实现https的方法示例

    环境说明 服务器系统:Ubuntu  18.04 64位 nginx:1.14 这篇文章主要是记录配置 https 的步骤,就不介绍申请ca证书的相关细节了 这里有免费的 ssl 证书:https://cloud.tencent.com/act/pro/ssl 我是西部数码的域名,在腾讯云申请的证书 申请证书并签发后,把证书先下载到本地 1.安装 nginx $ apt-get update // 更新软件 $ apt-get install nginx // 安装nginx 2.配置 ca 证

  • PHP实现获取域名的方法小结

    本文实例总结了PHP实现获取域名的方法.分享给大家供大家参考.具体实现方法如下: 方法一(用 系统变量) 复制代码 代码如下: //缺点不使用传递过来的地址和不支持系统变量的主机 echo $_SERVER['HTTP_HOST']; 方法二(用自带函数) 复制代码 代码如下: $url = 'http://www.jb51.net/index.php?referer=jb51.net'; $arr_url = parse_url($url); echo $arr_url['host']; 方法

  • js获取域名的方法

    本文实例讲述了js获取域名的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <script> //获取域名 var k_host = window.location.host; var k_host2 = document.domain; //获取页面完整地址 var k_url = window.location.href; </script> 运行结果如下: k_host:www.jb51.net k_host2:www.jb51.net k_url:ht

  • laravel-admin表单提交隐藏一些数据,回调时获取数据的方法

    表单提交时隐藏数据 读取最后一条的插入数据,但这样会造成如果两条数据同时插入,会并发出现错误 //忽略掉不需要保存的字段 $form->ignore(['column1', 'column2', 'column3']); 回调时获取数据 获取提交数据 // 在表单提交前调用 $form->submitted(function (Form $form) { //... }); //保存前回调 $form->saving(function (Form $form) { $form->u

  • PHP实现获取url地址中顶级域名的方法示例

    本文实例讲述了PHP实现获取url地址中顶级域名的方法.分享给大家供大家参考,具体如下: parse_url()获取到的host时多级域名,如:mp.weixin.qq.com.做域名黑名单的时候我们需要得到顶级域名. 有不足之处还请留言指正,谢谢. <?php /** * @Author: Ding Jianlong * @Date: 2019-03-07 16:14:04 * @Last Modified by: Ding Jianlong * @Last Modified time: 20

  • PHP实现搜索时记住状态的方法示例

    本文实例讲述了PHP实现搜索时记住状态的方法.分享给大家供大家参考,具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <hea

  • 阿里云Linux系统Nginx配置多个域名的方法详解

    Nginx绑定多个域名,可通过把多个域名规则写一个配置文件里实现,也可通过分别建立多个域名配置文件实现,为了管理方便,建议每个域名建一个文件,有些同类域名则可写在一个总的配置文件里. 1. 比如我想建立两个站点的域名分别是www.A.com 和 www.B.com,将这两个域名都解析到同一服务器IP. 2. 在Nginx配置文件conf目录下创建一个专门存放虚拟主机配置的目录,命名为vhosts,可以把虚拟目录的配置全部放在这里.如本例创建名为vhosts_A.conf和vhosts_B.con

随机推荐