Nginx虚拟主机多server_name的顺序问题

  |  |  
[ 2008-11-28 11:27 | by 张宴 ]
  [文章作者:张宴 本文版本:v1.0 最后修改:2008.11.28 转载请注明原文链接:http://blog.zyan.cc/post/382/]

  今天在配置Nginx + PHP + MediaWiki中,发现一个问题:MediaWiki所在的Nginx虚拟主机绑定了多个域名,但是不管通过什么域名访问MediaWiki首页,都会被跳转到其中的一个域名上。Nginx配置文件中没有相关的rewrite跳转规则,那么就应该是MediaWiki的PHP程序做的跳转,但是,遍历了MediaWiki目录下的所有文件以及查询了MySQL数据库中的每个表,都没有发现记录有这个域名。后来,通过查看源代码发现MediaWiki是根据$_SERVER['SERVER_NAME']做的跳转,顺藤摸瓜,发现了下列问题:

  在一个Nginx虚拟主机中,可以绑定多个server_name,例如:
  

  而server_name的先后顺序的不同,对PHP程序中使用$_SERVER["SERVER_NAME"]或getenv('SERVER_NAME')获取服务器域名是有影响的:
  

  

  $_SERVER["SERVER_NAME"]或getenv('SERVER_NAME')获取的始终将是Nginx server_name配置中的第一个域名,这一点在程序开发中需要注意。这第一个域名就相当于Apache虚拟主机配置中的ServerName,后面的域名就相当于Apache的ServerAlias。

  PS:以下是网友Daze的留言,希望对本文读者有所帮助。

引用
在某些情况下(具体可参考 wiki.nginx.org),Nginx 内部重定向规则会被启动,例如,当 URL 指向一个目录并且在最后没有包含“/”时,Nginx 内部会自动的做一个 301 重定向,这时会有两种情况:
1、server_name_in_redirect on(默认),URL 重定向为: server_name 中的第一个域名 + 目录名 + /;
2、server_name_in_redirect off,URL 重定向为: 原 URL 中的域名 + 目录名 + /。

当你有多个域名要指向同一个虚拟主机,并且你自己写 301 重定向规则把它们合并到某一个域名时,情况就更复杂了:
首先,nginx 检查 URL,如果符合条件,就用该规则(你写的)做第一遍重定向,接着,检查新生成的 URL,如果符合内部自动重定向之条件,就用前面提到的规则再做一次重定向。

至于 PHP 的 $_SERVER["SERVER_NAME"],在 nginx 中默认是由 nginx 的变量 $server_name 提供,这时它和重定向没有关系,始终是 server_name 设置中的第一个域名,但这是可以被改变的,在你的 nginx 配置中找到 fastcgi_param 部分,修改
fastcgi_param  SERVER_NAME    $server_name;

fastcgi_param  SERVER_NAME    $host;
但现在就要注意了,此时的 $_SERVER["SERVER_NAME"] 会受你写的和 nginx 自己的重定向规则所影响而变化。

现在就清楚了,如果 MediaWiki 是通过 $_SERVER["SERVER_NAME"] 来自己处理 URL 的话,那么在 nginx + php 的默认环境下,它获得的将始终是 server_name 设置中的第一个域名,所以造成了“不管通过什么域名访问 MediaWiki 首页,都会被跳转到其中的一个域名上。”,这不是 nginx 的重定向造成的,虽然默认 server_name_in_redirect 是 on,但这个指令的影响范围仅仅只是 nginx 自己内部的重定向规则,所以,当你在 nginx + php 的环境中使用多域名虚拟主机,并且你的 php 库、框架、代码大量使用 $_SERVER["SERVER_NAME"] 时,你也许应该:
1、设置 fastcgi_param  SERVER_NAME    $host;
2、设置 server_name_in_redirect off; 让 nginx 在处理自己内部重定向时不默认使用  server_name 设置中的第一个域名;
3、不要使用 nginx 的 rewrite 规则来重定向、合并多个域名。
当然,后俩条是完全可选的,前提是你清楚你在做什么并且小心处理这时的  $_SERVER["SERVER_NAME"],也许更好的做法是保持 fastcgi_param  SERVER_NAME    $server_name; ,然后合理使用 $_SERVER["SERVER_NAME"] 和 $_SERVER["HTTP_HOST"]。

这个问题确实很微妙,也许我的理解还是不完全,好在还有 curl ,慢慢研究了。 :-)

P.S. nginx 0.7.x 之前的版本还有一个指令 optimize_server_names 会影响内部重定向规则。

Nginx虚拟主机多server_name的顺序问题的更多相关文章

  1. Nginx高性能服务器安装、配置、运维 (5) —— Nginx虚拟主机配置

    六.Nginx虚拟主机配置 建立基于域名的虚拟主机: (1)建立基于域名的虚拟主机配置文件(以abc.com为例): (2)更改虚拟主机配置文件: 更改配置如下(更改部分即可): server { l ...

  2. Linux(7)- Nginx.conf主配置文件、Nginx虚拟主机/访问日志/限制访问IP/错误页面优化、Nginx反向代理、Nginx负载均衡

    一.Nginx.conf主配置文件 Nginx主配置文件conf/nginx.conf是一个纯文本类型的文件,整个配置文件是以区块的形式组织的.一般,每个区块以一对大括号{}来表示开始与结束. 核心模 ...

  3. nginx虚拟主机配置

    nginx虚拟主机配置   虚拟主机的概念虚拟主机,就是把一台物理服务器划分成多个"虚拟"的服务器,每一个虚拟主机都可以有独立的域名和独立的目录nginx虚拟主机的配置nginx的 ...

  4. Apache与Nginx虚拟主机设置(多域名和多端口的区别)

    为了方便管理虚拟主机,应该尽量少修改主配置文件http.conf或者nginx.conf,大部分修改变更都在虚拟主机片配置文件httpd- vhost.conf或者vhost.conf中完成,这样有利 ...

  5. Nginx教程(二) Nginx虚拟主机配置

    Nginx教程(二) Nginx虚拟主机配置 1 虚拟主机管理 1.1 Nginx管理虚拟主机 虚拟主机使用的是特殊的软硬件技术,它把一台运行在因特网上的服务器主机分成一台台“虚拟”的主机,每台虚拟主 ...

  6. 配置Nginx虚拟主机

    实验环境 一台最小化安装的CentOS 7.3虚拟机 配置基本环境 1. 安装nginx yum install -y epel-* yum isntall -y nginx vim 2. 建立虚机主 ...

  7. Nginx教程--02.Nginx虚拟主机的配置

    1.Nginx虚拟主机的配置 1.1 在conf目录下,使用命令 : vim nginx.conf 对上图解释: //全局区 worker _processes 1; //表示当前有1个工作的子进程, ...

  8. php管理nginx虚拟主机shell脚本

    使用php作为shell脚本是一件很方便的事情.理所当然,我们可以使用php脚本来管理 nginx虚拟主机,下面是笔者的 脚本 文件供各位参考 代码如下 复制代码 #!/usr/bin/php -q& ...

  9. Nginx 虚拟主机 VirtualHost 配置

    Nginx 是一个轻量级高性能的 Web 服务器, 并发处理能力强, 对资源消耗小, 无论是静态服务器还是小网站, Nginx 表现更加出色, 作为 Apache 的补充和替代使用率越来越高. 我在& ...

随机推荐

  1. 技术简历写这么写,才能得到BAT面试官们的青睐

    公众号[程序员江湖] 作者陆小凤,985 软件硕士,阿里 Java 研发工程师,在技术校园招聘.自学编程.计算机考研等方面有丰富经验和独到见解,目前致力于分享程序员干货和学习经验,同时热衷于分享作为程 ...

  2. ArcEngine二次开发之提取外包矩

    1.通过ITopologicalOperator接口,此方法适用于需要获得包含几个或多个要素的最小外包矩形 public IEnvelope GetEnvelope(IGeometryCollecti ...

  3. VS2008新增文件没有模板

    可能是我安装的过程中发神经没有选中选项什么的,打开来想建个项目发现一个模板都没有,那就很尴尬了,作为对开发工具极度依赖的人,这真的难受... 在网上找到别人的办法 开始 –> 程序 –> ...

  4. 微服务之服务注册与发现--Eureka(附代码)

    该贴为入门贴,看完可快速知道服务注册与发现是什么?怎么用?至于深入的内容不在此篇文章所述之内,请自行百度. 内容来自:https://blog.csdn.net/nanbiebao6522/artic ...

  5. Linux 防火墙开放特定端口 (iptables)

    1.查看状态:iptables -L -n2.直接编辑:vi /etc/sysconfig/iptables3.端口开放:-A INPUT -m state --state NEW -m tcp -p ...

  6. C++面试题整理(持续更新中)

    一. 内联函数和宏定义的区别 1.内联函数在运行时可调试,而宏定义不可以: 2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通类型),而宏定义不会: 3.内联函数可以访问类的成员变量,而 ...

  7. 小记---------sparkRDD的Transformation 和 Action 及案例 原理解释

    RDD :弹性分布式数据集:是一个容错的.并行的数据结构,可以让用户显式地将数据存储到磁盘或内存中,并控制数据的分区   RDD是Spark的核心数据结构,通过RDD的依赖关系形成Spark的调度顺序 ...

  8. P1004方格取数

    这是提高组得一道动态规划题,也是学习y氏思考法的第一道题. 题意为给定一个矩阵,里面存有一些数,你从左上角开始走到右下角,另一个人从右下角开始走到左上角,使得两个人取数之和最大,当然一个数只可以取走一 ...

  9. Ubuntu基本操作(博主想上传图片给服务器的一些命令)

    1.将当前目录下的文件移动至指定文件夹,这里用移动至网站的根目录做示范 sudo mv bamboo.jpg /val/www/html mv bamboo.jpg /val/www/html 2.进 ...

  10. c++ 【递归算法】梵塔问题

    一道递归水题,2话不说,直接放代码: #include<iostream> using namespace std; int k; void move(int m,char a,char ...