2015年2月9日 星期一

PHP 取得 nginx 的 Server Name 不如預期

一般 PHP 會用 $_SERVER["SERVER_NAME"] 取得網站的網域名稱。
SERVER_NAME 這個值,是在網頁伺服器中設定,如果 Server 只設定一個網域名稱,不會有問題。但如果設定多個別名在 Apache 和 Nginx 則會有不同的結果。

Apache + PHP
設定多個網域,在 Apache 的 VirtualHost 設定,可能像這樣
ServerName a1.example.com
ServerAlias a2.example.com
ServerAlias a3.example.com
分別訪問 a1.example.com、a2.example.com、a3.example.com,
$_SERVER["SERVER_NAME"] 的值也會分別是 a1.example.com、a2.example.com、a3.example.com,
這看起來很合理,但要注意一點,假設有一個網域 a4.example.com 也可以訪問到這個站,
雖然 Server 中沒設定 a4.example.com,但 $_SERVER["SERVER_NAME"] 的值也會是 a4.example.com


Nginx + PHP
同樣的情況,換到 Nginx 上。
設定多個網域,在 Nginx 設定,可能像這樣
server_name a1.example.com a2.example.com a3.example.com
分別訪問 a1.example.com、a2.example.com、a3.example.com,
$_SERVER["SERVER_NAME"] 的值永遠只會是第一項設定 a1.example.com,
這對之前在 apache 使用 $_SERVER["SERVER_NAME"] 的程式,移到 Nginx 時,會造成不少困擾。
後來發現 Nginx 的 server_name 設定,可以用正規表示式(Regular expression)來寫,
我想既然 Nginx 只會回應第一個設定值,那我把三個網域寫成一個正規表示式,只放一個,應該可以解決吧?
但,天不從人願,這樣做的結果是,$_SERVER["SERVER_NAME"] 直接顯示那個正規表示式。
最後,只好修改 fastcgi_params 設定檔裡面的變數設定,

fastcgi_param  SERVER_NAME        $server_name;
改成
fastcgi_param  SERVER_NAME        $host;


參考:
showing correct server_name to fcgi (php) 
http://nginx.org/en/docs/http/server_names.html
Nginx regex vhost pattern ends up as PHP server name

沒有留言:

張貼留言