nginx
在收到一條請求時將先通過 server_name
匹配一個 server
, 然後使用 server
中的 location
繼續匹配.
匹配 server_name
在 nginx
中, server_name
決定了當收到一個請求後哪一個 server
會被使用. nginx
會使用請求頭中的 Host
欄位與 server_name
進行匹配. 定義 server_name
時可以使用 完全名稱
、萬用字元名稱
、正規表示式名稱
, 它們的匹配順序如下:
- 完全匹配
- 前萬用字元匹配, 即
*.example.org
- 後萬用字元匹配, 即
mail.*
- 正規表示式匹配
如果沒有匹配到結果, 將會使用 default_server
進行處理, 如果沒有定義, 則第一個定義的為 default_server
. 使用三個簡單的 server
作為例子, 讓他們監聽 80
埠, server_name
分別設定為 *.org
、*.net
、*.com
:
server {
listen 80;
server_name example.org www.example.org;
return 401;
}
server {
listen 80;
server_name example.net www.example.net;
return 402;
}
server {
listen 80;
server_name example.com www.example.com;
return 403;
}
複製程式碼
在上面的配置中, 預設的伺服器為 第一個
, 隨便訪問一個不存在的 server
將會返回 401
. 不過可以使用 default_server
手動設定一個預設主機, default_server
設定在 listen
欄位, 如下:
server {
listen 80 default_server;
server_name example.net www.example.net;
}
複製程式碼
之後再匹配時, 未匹配到將會使用這個 server
.
禁止訪問
如果想要禁止一個沒有攜帶 Host
欄位的請求, 可以定義如下 server
:
server {
listen 80;
server_name "";
return 444;
}
複製程式碼
server_name
定義為空字串, 如果 Host
欄位為空或不存在, 將會匹配到這個 server
, 然後返回 404
狀態碼.
Nginx
的444
狀態比較特殊,如果返回444
那麼客戶端將不會收到服務端返回的資訊,就像是網站無法連線一樣, 瀏覽器直接顯示502
. 但是如果使用反向代理, 還是顯示正常狀態碼
如果想要禁止訪問不存在的主機, 可以這樣定義:
server {
listen 80 default_server;
server_name _;
return 444;
}
複製程式碼
_
在這裡沒有任何特別含義, 因為一個域名中不會出現 _
, 所以不會與任何真實的域名相同, 使用其他非法字元是相同的道理.
同時匹配 IP
和 server_name
現在來看一下對於監聽不同 IP
和不同 server_name
混合使用時是如何處理的:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
}
server {
listen 192.168.1.1:80;
server_name example.net www.example.net;
}
server {
listen 192.168.1.2:80;
server_name example.com www.example.com;
}
複製程式碼
在這個配置中, nginx
首先匹配 IP
, 匹配到後再匹配它們的 server_name
, 如果沒有匹配到 server_name
, 則使用到它們預設的 server
. 舉個例子, 如果一個域名為 www.example.com
的請求來自 192.168.1.1:80
. 但是監聽 192.168.1.1:80
的 server
只有兩個, 這兩個都不能匹配 www.example.com
, 那麼就使用這兩個 server
中的預設主機, 由於沒有使用 defualt_server
定義監聽, 所以預設為第一個即 www.example.org
這個 server
. 當然你可以定義 defualt_server
:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
}
server {
listen 192.168.1.1:80 default_server;
server_name example.net www.example.net;
}
server {
listen 192.168.1.2:80 default_server;
server_name example.com www.example.com;
}
複製程式碼
匹配 location
在 nginx
匹配到一個 server
後, 就會通過 location
繼續處理請求, 下面是一個示例:
server {
listen 172.17.0.3:80;
server_name _;
location / {
return 401;
}
location ~*\.(gif|jpg|png)$ {
return 402;
}
location ~*\.(gif|jpg|png)$ {
return 404;
}
location /api {
return 403;
}
}
複製程式碼
nginx
首先會在所有的 location
中搜尋 字首
進行匹配, 匹配到字首後, 將按順序匹配使用 正規表示式
定義的 location
, 匹配到就結束, 如果沒有匹配到, 則使用之前匹配到字首的那個 location
進行處理, 下面是具體匹配的例子:
- 一個
/x.gif
請求, 首先匹配到的字首為/
, 然後使用剩下的x.gif
跟location
的正則去匹配, 先匹配到了location ~*\.(gif|jpg|png)$
, 返回402
. - 一個
/x.pdf
請求, 由於x.pdf
無法被匹配到, 所以使用location /
進行處理. - 一個
/api/x.gif
, 首先匹配到字首為/api
, 然後使用剩下的x.gif
跟location
的正則去匹配, 先匹配到了location ~*\.(gif|jpg|png)$
, 返回402
. - 一個
/api/x.pdf
請求, 由於x.pdf
無法被匹配到, 所以使用location /api
進行處理.