$_SERVER["SERVER_NAME"]獲取問題

在使用nginx中,當nginx裏的server_name配置了多個域名的時候,發現$_SERVER["SERVER_NAME"]獲取的域名是第一個而不是第二個或者第三個

既然有問題,就肯定有解決方案。。。。。。在百度主翻了N久,終於找到了需要的資料!原來:$_SERVER[“SERVER_NAME”] 返回的值是由 Nginx 的 fastcgi_param 中 SERVER_NAME 提供的,而默認的配置爲:

fastcgi_param  SERVER_NAME    $server_name;

Nginx中 $server_name 變量就是上面設置的域名,只會返回第一個!

這下好辦了,把上面的配置改成:

fastcgi_param  SERVER_NAME    $host;

就行了。
另外還需要在server_name配置後面加一行:

server_name_in_redirect off;

意思是 讓 nginx 在處理自己內部重定向時不默認使用 server_name 設置中的第一個域名!

$_SERVER['SERVER_NAME']; 如果有域名返回域名,沒有域名返回IP地址

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.conf配置:
第一個server:
server_name  *.myhz.com;
root  /wwwroot/myhz.com;
第二個server:
server_name  *.paidc.com;
root  /wwwroot/paidc.com;
文件內容:
/wwwroot/myhz.com/index.php的內容是:
<?
if (count(explode('a.myhz.com',$_SERVER['SERVER_NAME']))>1)
{
echo "a.myhz";
        exit();
}
else if (count(explode('b.test.com',$_SERVER['SERVER_NAME']))>1)
{
echo "b.myhz";
        exit();
}
else
echo $_SERVER['SERVER_NAME'];
?>

/wwwroot/paidc.com/index.php的內容是:
<?
if (count(explode('a.paidc.com',$_SERVER['SERVER_NAME']))>1)
{
echo "a.paidc";
        exit();
}
else if (count(explode('b.paidc.com',$_SERVER['SERVER_NAME']))>1)
{
echo "b.paidc";
        exit();
}
else
echo $_SERVER['SERVER_NAME'];
?>

訪問的結果是:
a.myhz.com顯示*.myhz.com
b.myhz.com顯示*.myhz.com
a.paidc.com顯示*.paidc.com
b.paidc.com顯示*.paidc.com
知道怎麼回事了吧?
就是nginx能區分出來*.myhz.com和*.paidc.com
*.myhz.com確實解析到了/wwwroot/myhz.com目錄,但是php程序區分不出來a.myhz.com和b.myhz.com
*.paidc.com確實解析到了/wwwroot/paidc.com目錄,但是php程序區分不出來a.paidc.com和b.paidc.com

如果將兩個index.php文件中的$_SERVER['SERVER_NAME']換成 $_SERVER["HTTP_HOST"]
訪問結果是:
a.myhz.com顯示a.myhz
b.myhz.com顯示b.myhz
a.paidc.com
顯示a.paidc
b.paidc.com顯示b.paidc
這麼說來,就一切OK了

參考:http://ivan.xin/?p=1620

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章