Nginx $host變量詳解

原創(chuàng)文章出自公眾號(hào):「碼農(nóng)富哥」,如需轉(zhuǎn)載請(qǐng)請(qǐng)注明出處!
文章如果對(duì)你有收獲,可以收藏轉(zhuǎn)發(fā),這會(huì)給我一個(gè)大大鼓勵(lì)喲!另外可以關(guān)注我公眾號(hào)「碼農(nóng)富哥」 (搜索id:coder2025),我會(huì)持續(xù)輸出Python,算法,計(jì)算機(jī)基礎(chǔ)的 原創(chuàng) 文章

$host變量的官方解釋

$host:in this order of precedence: host name from the request line, or host name from the “Host” request header field, or the server name matching a request

host變量的值按照如下優(yōu)先級(jí)獲得:

  1. 請(qǐng)求行中的host.
  2. 請(qǐng)求頭中的Host頭部.
  3. 與一條請(qǐng)求匹配的server name.

什么是請(qǐng)求行中的host

我們知道,HTTP是一個(gè)文本協(xié)議,建立在一個(gè)可靠的傳輸層協(xié)議之上。這個(gè)傳輸層協(xié)議要是可靠的,面向連接的。由于TCP的普及程度,讓它成了HTTP下層協(xié)議事現(xiàn)上的標(biāo)準(zhǔn)。但我們要知道,HTTP并不僅限于建立在TCP之上。只要是可靠的,面向連接的傳輸層協(xié)議,都可以用來(lái)傳輸HTTP。下面所說(shuō)的HTTP,都是指搭載在TCP之上的HTTP。

一個(gè)HTTP請(qǐng)求過(guò)程是這樣的,客戶端先與服務(wù)器建立起TCP連接,然后再與服務(wù)器端進(jìn)行請(qǐng)求和回復(fù)的收發(fā)。請(qǐng)求包含請(qǐng)求行、請(qǐng)求頭和請(qǐng)求體,其中,根據(jù)請(qǐng)求方法的不同,請(qǐng)求體是可選的。

在發(fā)送請(qǐng)求行之前,客戶端與服務(wù)器已經(jīng)建立了連接。所以此時(shí)請(qǐng)求行中并不需要有服務(wù)器的信息。我們用telnet測(cè)試, 例如:

GET /index.php HTTP/1.1

這就是一個(gè)完整的HTTP請(qǐng)求行。雖然請(qǐng)求行中不需要有服務(wù)器的信息,但仍然可以在請(qǐng)求行中包含服務(wù)器的信息。例如:

GET www.test.info/index.php HTTP/1.1

兩者一比較,就很容易理解什么叫請(qǐng)求行中的host了。第一個(gè)請(qǐng)求行中,就沒(méi)有host,第二種請(qǐng)求行中,就帶了host,為www.test.info。

Host請(qǐng)求頭與HTTP/1.0、HTTP/1.1

一個(gè)請(qǐng)求,請(qǐng)求行下面就是一些列的請(qǐng)求頭。這些請(qǐng)求頭,在HTTP/1.0中,都是可選的,且HTTP/1.0不支持Host請(qǐng)求頭;而在HTTP/1.1中,Host請(qǐng)求頭部必須存在,否則會(huì)返回400 Bad Request
我們看個(gè)例子, 使用telnet 連接:

GET /index.php HTTP/1.1

HTTP/1.1 400 Bad Request
Server: nginx/1.4.6 (Ubuntu)

但是HTTP/1.0是不支持Host頭部的,所以請(qǐng)求,不需要帶這個(gè)Host,我們也測(cè)試一下:

HEAD /rec/app/detail/youxidaren.html HTTP/1.0

HTTP/1.1 404 NOT FOUND
Server: nginx/1.4.6 (Ubuntu)

可以看到?jīng)]有返回400, 而是返回了404,說(shuō)明這個(gè)請(qǐng)求還是來(lái)到nginx處理,命中了其中一個(gè)配置的"虛擬主機(jī)", 我到nginx下面看access_log,看到日志寫(xiě)在了第一個(gè)的nginx虛擬主機(jī)配置的日志文件下面,說(shuō)明http1.0情況下,沒(méi)有帶host頭部,請(qǐng)求默認(rèn)來(lái)到了nginx 第一個(gè)虛擬主機(jī)下處理。

什么是與請(qǐng)求匹配的server name

server name是指在Nginx配置文件中,在server塊中,用server_name指令設(shè)置的值。一個(gè)server可以多次使用server_name指令,來(lái)實(shí)現(xiàn)俗稱的“虛擬主機(jī)”。例如:

server {  
    listen      80;  
    server_name example.org www.example.org;  
    ...  
}  
  
server {  
    listen      80;  
    server_name example.net www.example.net;  
    ...  
}  
  
server {  
    listen      80;  
    server_name example.com www.example.com;  
    ...  
}  

關(guān)于虛擬主機(jī)的確定方法,還是引用Nginx的官方文檔:

在這個(gè)配置中,nginx僅僅檢查請(qǐng)求的“Host”頭以決定該請(qǐng)求應(yīng)由哪個(gè)虛擬主機(jī)來(lái)處理。如果Host頭沒(méi)有匹配任意一個(gè)虛擬主機(jī),或者請(qǐng)求中根本沒(méi)有包含Host頭,那nginx會(huì)將請(qǐng)求分發(fā)到定義在此端口上的默認(rèn)虛擬主機(jī)。在以上配置中,第一個(gè)被列出的虛擬主機(jī)即nginx的默認(rèn)虛擬主機(jī)——這是nginx的默認(rèn)行為。而且,可以顯式地設(shè)置某個(gè)主機(jī)為默認(rèn)虛擬主機(jī),即在”listen”指令中設(shè)置”default_server”參數(shù):
server {
listen 80 default_server;
server_name example.net www.example.net;

}

這就解釋了上面的HTTP1.0請(qǐng)求,不帶Host頭,默認(rèn)來(lái)到了第一個(gè)配置的server處理了。
然后我測(cè)試一下把www.test.info這個(gè)域名設(shè)成默認(rèn)的主機(jī)default_server,看請(qǐng)求能不能正常來(lái)到www.test.info這個(gè)server來(lái)處理。

nginx 配置修改:

server {
    listen      80 default_server;
    server_name www.test.info
}

再次請(qǐng)求:

HEAD /index.php HTTP/1.0

HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)

實(shí)際測(cè)試,正常,default_server確實(shí)起作用了。

延伸: Nginx 的 host 與http_host 的區(qū)別

host 是nginx的官方變量,可以從官方查詢http_host 則是讀取請(qǐng)求頭header里面的key,所有請(qǐng)求頭里面的key再nginx里面都可以通過(guò)小寫(xiě)和下劃線來(lái)讓nginx讀取。例如header里面的Host就能轉(zhuǎn)成http_host, user_agent可以轉(zhuǎn)成http_user_agent。
所以,只要是header的請(qǐng)求頭都可以這樣被nginx讀取, 我們測(cè)試一下:

HEAD /rec/app/detail/youxidaren.html HTTP/1.1 
Host: mo.ouwan.com
Content-type: html/txt
Test-key: test-value

HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Thu, 22 Mar 2018 12:28:56 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Vary: Cookie
# 這三個(gè)頭都是我請(qǐng)求的時(shí)候加的。
x_host: mo.ouwan.com
x_test_key: test-value
x_content_type: html/txt

當(dāng)然這個(gè)幾個(gè)頭部能在response顯示是因?yàn)樵趎ginx加了add_header控制的:

location / {
        add_header x_host   $http_host;
        add_header x_test_key $http_test_key;
        add_header x_content_type $http_content_type;
}

$http_header的應(yīng)用:當(dāng)我們一個(gè)項(xiàng)目部署在兩個(gè)服務(wù)器下面,然后在另外一個(gè)服務(wù)器搭建nginx反響代理,反響代理把請(qǐng)求轉(zhuǎn)發(fā)給兩個(gè)服務(wù)器的時(shí)候,他們的日志記錄的是反向代理的ip, 而不是真正請(qǐng)求的用戶IP, 這時(shí)就可以通過(guò)配置proxy_set_header 把真實(shí)IP設(shè)置給一個(gè)X-forwarded-For 或者 X-Real-IP 轉(zhuǎn)給后端服務(wù)器,然后后端服務(wù)器讀取通過(guò)http_x_real_ip來(lái)讀取真實(shí)IP, 記錄到access_log下面

 location / {
                proxy_pass http://tg_web_cluster;
                proxy_set_header Host      $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                # proxy_set_header X-Forwarded-Proto $scheme;
        }

日志的格式把第一個(gè)IP換成剛才轉(zhuǎn)發(fā)過(guò)來(lái)的頭部X-Real-IP就可以記錄用戶IP了:

    log_format tg_log '$http_x_real_ip - $remote_user [$time_local] '
                '"$request" $status $body_bytes_sent '
                '"$http_referer" "$http_user_agent" "$gzip_ratio" - $request_time';

總結(jié):

  • $host變量的值按照如下優(yōu)先級(jí)獲得:
  1. 請(qǐng)求行中的host.
  2. 請(qǐng)求頭中的Host頭部.
  3. 與一條請(qǐng)求匹配的server name.
  • nginx 可以通過(guò)$http_header讀取請(qǐng)求頭的值,實(shí)際應(yīng)用就可以負(fù)載均衡的時(shí)候讀取IP

參考:

關(guān)于nginx中的host變量
What's the difference of host andhttp_host in Nginx

最后

原創(chuàng)文章出自公眾號(hào):「碼農(nóng)富哥」,如需轉(zhuǎn)載請(qǐng)請(qǐng)注明出處!
文章如果對(duì)你有收獲,可以收藏轉(zhuǎn)發(fā),這會(huì)給我一個(gè)大大鼓勵(lì)喲!另外可以關(guān)注我公眾號(hào)「碼農(nóng)富哥」 (搜索id:coder2025),我會(huì)持續(xù)輸出Python,算法,計(jì)算機(jī)基礎(chǔ)的 原創(chuàng) 文章

掃碼關(guān)注我:碼農(nóng)富哥
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,569評(píng)論 19 139
  • 第一章 Nginx簡(jiǎn)介 Nginx是什么 沒(méi)有聽(tīng)過(guò)Nginx?那么一定聽(tīng)過(guò)它的“同行”Apache吧!Ngi...
    JokerW閱讀 33,022評(píng)論 24 1,002
  • Nginx簡(jiǎn)介 解決基于進(jìn)程模型產(chǎn)生的C10K問(wèn)題,請(qǐng)求時(shí)即使無(wú)狀態(tài)連接如web服務(wù)都無(wú)法達(dá)到并發(fā)響應(yīng)量級(jí)一萬(wàn)的現(xiàn)...
    魏鎮(zhèn)坪閱讀 2,214評(píng)論 0 9
  • Page 1:nginx 服務(wù)器安裝及配置文件詳解 CentOS 6.2 x86_64 安裝 nginx 1.1 ...
    xiaojianxu閱讀 8,680評(píng)論 1 41
  • 夢(mèng)中,睡醒一覺(jué),拉開(kāi)一面墻的窗簾和落地窗,瞬間看到窗外是一汪大海。 清晨的海風(fēng)微微撲面,藍(lán)藍(lán)的海無(wú)窮無(wú)盡,海浪一陣...
    婷fish閱讀 316評(píng)論 0 0

友情鏈接更多精彩內(nèi)容