nginx server_name配置多個(gè)域名時(shí)的坑
server_name 指令詳解
server_name 指令設(shè)置基于域名的虛擬主機(jī),?個(gè)ip的服務(wù)器可以配置多個(gè)域名。下?這些server_name是有效的:
- server_name domain.com;
- server_name domain.com www.domain.com;
- server_name *.domain.com;
- server_name .domain.com;
- server_name domain.*;
- server_name "";
多個(gè)域名之間以空格分隔。nginx允許?個(gè)虛擬主機(jī)有?個(gè)或多個(gè)名字,也可以使?通配符"*"來(lái)設(shè)置虛擬主機(jī)的名字。
server_name指令在接到請(qǐng)求后的匹配順序分別為:
- 1、準(zhǔn)確的server_name匹配,例如:domain.com www.domain.com
- 2、以通配符開(kāi)始的字符串: .domain.com .domain.com
- 3、以通配符結(jié)束的字符串:www.
- 4、匹配正則表達(dá)式:~^(?.+).domain.com$
nginx將按照1,2,3,4的順序?qū)erver name進(jìn)?匹配,有?項(xiàng)匹配以后就會(huì)停?搜索,類(lèi)似于location指令。
背景
為了區(qū)分線上環(huán)境和測(cè)試環(huán)境,我弄了個(gè)自己測(cè)試專(zhuān)用的域名test.daemoncoder.com,線上環(huán)境的正式域名是www.daemoncoder.com。nginx里的server_name配置改為:
# 只列出了我們關(guān)心的配置,省略了其他無(wú)關(guān)部分
server {
server_name www.daemoncoder.com test.daemoncoder.com;
...
}但是使用時(shí)發(fā)現(xiàn)請(qǐng)求一直報(bào)錯(cuò),重定向到錯(cuò)誤頁(yè)面,于是開(kāi)始了問(wèn)題的定位。
問(wèn)題的定位
根據(jù)業(yè)務(wù)上報(bào)錯(cuò)時(shí)打的日志,定位到請(qǐng)求公共處理的部分里有這么一個(gè)判斷:
if ($_SERVER['SERVER_NAME'] != parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) {
$this->redirectError();
}判斷請(qǐng)求referer里解析出的域名如果和nginx里的$server_name變量里的域名如果不一樣,就跳到錯(cuò)誤頁(yè)面,也是前面說(shuō)的問(wèn)題。
那么問(wèn)題來(lái)了,看referer中的域名為什么和 $_SERVER['SERVER_NAME'] 不一致呢?我請(qǐng)求用的鏈接形式如 http://test.daemoncoder.com/xxx 這種形式,但是最終在PHP這一層取到 $_SERVER['SERVER_NAME'] 的值為 www.daemoncoder.com,而 HTTP_REFERER 里的域名為:test.daemoncoder.com。
可以看到 SERVER_NAME 的取值和我們的預(yù)期不一致,nginx是怎么把這個(gè)變量傳過(guò)來(lái)的,需要從 nginx 的 fastcgi_params 配置文件中找一下 SERVER_NAME 的定義:
fastcgi_param SERVER_NAME $server_name;
可以看到 nginx 里的 $server_name 變量就是我們PHP里取的$_SERVER['SERVER_NAME'] 的來(lái)源。
問(wèn)題的原因
通過(guò)上面的定位,我們基本可以看到問(wèn)題的根本原因了(敲黑板,劃重點(diǎn)):
當(dāng)nginx配置里一個(gè)server節(jié)點(diǎn)下,server_name配置多個(gè)域名時(shí),$server_name變量的值都是配置的第一個(gè)。
再回顧下我的 nginx 配置:
# 只列出了我們關(guān)心的配置,省略了其他無(wú)關(guān)部分
server {
server_name www.daemoncoder.com test.daemoncoder.com;
...
}server_name 結(jié)點(diǎn)有兩個(gè):www.daemoncoder.com 和 test.daemoncoder.com,當(dāng)我用測(cè)試域名去訪問(wèn)頁(yè)面的時(shí)候,可以匹配到 test.daemoncoder.com 這個(gè)域名,所以會(huì)根據(jù)當(dāng)前這個(gè)server節(jié)點(diǎn)的配置來(lái)處理這個(gè)請(qǐng)求,但是 nginx 會(huì)把 $server_name 的值設(shè)置為當(dāng)前 server 節(jié)點(diǎn)的配置的第一個(gè) server_name,也就是 www.daemoncoder.com。如果配置改為:
server_name test.daemoncoder.com www.daemoncoder.com;
那么用測(cè)試域名請(qǐng)求就可以得到期望的值了(但是正式域名就出問(wèn)題了)。
解決方式
第一種方式就是把配置文件按域名拆分到各自單獨(dú)的server節(jié)點(diǎn)下,也就是:
# 省略其他無(wú)關(guān)部分
server {
server_name www.daemoncoder.com;
...
}
server {
server_name test.daemoncoder.com;
...
}這樣用不同的域名訪問(wèn)會(huì)落到各自對(duì)應(yīng)的配置中,解析到的 $server_name 也都是各自的值。
第二種方式是修改 nginx SERVER_NAME 使用 $host 變量, 也就是把
fastcgi_param SERVER_NAME $server_name;
修改為:
fastcgi_param SERVER_NAME $host;
$host變量的解析都是當(dāng)前請(qǐng)求的host,不會(huì)受 server_name 是否配置多個(gè)域名的影響,這樣我們?cè)赑HP里取 $_SERVER['SERVER_NAME'] 取出的值就是實(shí)際請(qǐng)求的域名,也可以解決問(wèn)題(但是代碼里的這個(gè)判斷邏輯在測(cè)試環(huán)境似乎就沒(méi)有意義了,問(wèn)題不大)。
其他
有多個(gè)域名時(shí)(server_name other.domain.com www. domain.com;):fastcgi_param SERVER_NAME $server_name ,$server_name 會(huì)取值第一個(gè)域名(other.domain.com)。
$host 有可能等于 $server_name ,也可能是IP地址(直接通過(guò)訪問(wèn)此優(yōu)先順序取值:請(qǐng)求行中的主機(jī)名,或“主機(jī)”請(qǐng)求標(biāo)頭字段中的主機(jī)名,或與請(qǐng)求匹配的服務(wù)器名。
$1|$2|$3 ...是nginx在匹配正則時(shí)生成的變量,用于捕獲一個(gè)正則表達(dá)式括號(hào)中匹配的字符串(從左到右依次存儲(chǔ)在$1|$2|$3 ...中),新值覆蓋舊值,可以使用變量保存需要用到的值:set $pre $1
到此這篇關(guān)于nginx server_name配置多個(gè)域名時(shí)的坑的文章就介紹到這了,更多相關(guān)nginx server_name配置多個(gè)域名內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
LNMP 解決Access Denied錯(cuò)誤詳細(xì)介紹
這篇文章主要介紹了LNMP 解決Access Denied錯(cuò)誤詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2016-10-10
Nginx?HttpHeader增加幾個(gè)關(guān)鍵的安全選項(xiàng)問(wèn)題小結(jié)
本文給大家介紹Nginx?HttpHeader增加幾個(gè)關(guān)鍵的安全選項(xiàng)問(wèn)題小結(jié),結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-12-12
Nginx搭配cpolar實(shí)現(xiàn)遠(yuǎn)程開(kāi)發(fā)無(wú)縫協(xié)作全過(guò)程
Nginx是一款高性能的本地Web服務(wù)器,以其卓越的穩(wěn)定性和靈活的配置能力,成為開(kāi)發(fā)者搭建本地服務(wù)的首選工具,本文將介紹如何利用 Ubuntu操作系統(tǒng)、Docker容器技術(shù)以及cpolar內(nèi)網(wǎng)穿透工具來(lái)實(shí)現(xiàn)公網(wǎng)遠(yuǎn)程訪問(wèn)本地Nginx服務(wù)器的具體操作流程,需要的朋友可以參考下2026-01-01
nginx搭建圖片服務(wù)器的過(guò)程詳解(root和alias的區(qū)別)
這篇文章主要介紹了nginx搭建圖片服務(wù)器(root和alias的區(qū)別)的過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
Nginx中l(wèi)ocation實(shí)現(xiàn)多條件匹配的方法詳解
在 Nginx 中,location 指令用于匹配請(qǐng)求的 URI,雖然 location 本身是基于單一匹配規(guī)則的,但可以通過(guò)多種方式實(shí)現(xiàn)多個(gè)條件的匹配邏輯,下面小編就來(lái)為大家介紹一下具體實(shí)現(xiàn)方法吧2025-03-03
國(guó)內(nèi)一些常用PHP的CMS的Nginx服務(wù)器的偽靜態(tài)規(guī)則整理
當(dāng)我們從apache服務(wù)器轉(zhuǎn)向Nginx服務(wù)器的時(shí)候,它們的偽靜態(tài)規(guī)則就不一樣了,所以你熟悉Nginx服務(wù)器的偽靜態(tài)規(guī)則,自己寫(xiě)當(dāng)然也好2011-03-03
nginx后端節(jié)點(diǎn)的健康檢查和nginx平滑升級(jí)方式
本文介紹了Nginx反向代理的ngx_http_proxy_module和ngx_http_upstream_module模塊,以及淘寶開(kāi)發(fā)的nginx_upstream_check_module模塊,并介紹了Nginx平滑升級(jí)原理及實(shí)戰(zhàn)操作,最后總結(jié)了Nginx版本升級(jí)的方法2026-04-04

