zoukankan      html  css  js  c++  java
  • Nginx虚拟主机多server_name的顺序问题

    今天在配置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 会影响内部重定向规则。
  • 相关阅读:
    [Leetcode] 221. Maximal Square
    [翻译] TensorFlow Programmer's Guide之Frequently Asked Questions(问得频率最多的几个问题)
    [Kaggle] dogs-vs-cats之模型训练
    [Kaggle] dogs-vs-cats之建立模型
    [Kaggle] dogs-vs-cats之制作数据集[1]
    Linux虚拟机Centos 设置固定的静态IP
    linux IP动态变动之后 , 需要做的杂项操作
    GitBlit (1)-- 在linux 安装 GitBlit 并运行
    Linux 安装SVN
    微信开发(3) -- 支付后接收回调信息测试
  • 原文地址:https://www.cnblogs.com/top5/p/1588478.html
Copyright © 2011-2022 走看看