nginx 如何處理請求

如何防止處理未定義伺服器名稱的請求
混合式名稱與 IP 位址的虛擬伺服器
一個簡單的 PHP 網站設定

基於名稱的虛擬伺服器

nginx 首先決定哪個伺服器應該處理請求。讓我們先從一個簡單的設定開始,其中所有三個虛擬伺服器都監聽 *:80 連接埠

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;
    ...
}

在此設定中,nginx 只會測試請求的「Host」標頭欄位,以確定請求應路由到哪個伺服器。如果其值與任何伺服器名稱都不匹配,或者請求根本不包含此標頭欄位,則 nginx 會將請求路由到此連接埠的預設伺服器。在上述設定中,預設伺服器是第一個 — 這是 nginx 的標準預設行為。也可以使用listen 指令中的 default_server 參數來明確設定哪個伺服器應為預設伺服器

server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}

default_server 參數自 0.8.21 版本起可用。在較早的版本中,應改用 default 參數。

請注意,預設伺服器是監聽連接埠的屬性,而不是伺服器名稱的屬性。稍後將詳細介紹。

如何防止處理未定義伺服器名稱的請求

如果應該禁止沒有「Host」標頭欄位的請求,可以定義一個只會丟棄請求的伺服器

server {
    listen      80;
    server_name "";
    return      444;
}

在這裡,伺服器名稱設定為空字串,這將會匹配沒有「Host」標頭欄位的請求,並會傳回特殊的 nginx 非標準程式碼 444,這將會關閉連線。

自 0.8.48 版本起,這是伺服器名稱的預設設定,因此可以省略 server_name ""。在較早的版本中,機器的主機名稱會被用作預設伺服器名稱。

混合式名稱與 IP 位址的虛擬伺服器

讓我們看看更複雜的設定,其中一些虛擬伺服器監聽不同的位址

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 首先根據 server 區塊的 listen 指令測試請求的 IP 位址和連接埠。然後,它會根據匹配 IP 位址和連接埠的 server 區塊的 server_name 條目測試請求的「Host」標頭欄位。如果找不到伺服器名稱,則該請求將由預設伺服器處理。例如,在 192.168.1.1:80 連接埠上收到的 www.example.com 的請求將由 192.168.1.1:80 連接埠的預設伺服器處理,也就是第一個伺服器,因為沒有為此連接埠定義 www.example.com

如前所述,預設伺服器是監聽連接埠的屬性,並且可以為不同的連接埠定義不同的預設伺服器

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;
    ...
}

一個簡單的 PHP 網站設定

現在,讓我們看看 nginx 如何選擇一個位置來處理典型、簡單的 PHP 網站的請求

server {
    listen      80;
    server_name example.org www.example.org;
    root        /data/www;

    location / {
        index   index.html index.php;
    }

    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }

    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

nginx 首先搜尋由文字字串給定的最明確前綴位置,而不管列出的順序。在上述設定中,唯一的前綴位置是「/」,由於它匹配任何請求,因此它將被用作最後的手段。然後,nginx 會按照設定檔中列出的順序檢查由正規表示式給定的位置。第一個匹配的表示式會停止搜尋,nginx 將使用這個位置。如果沒有正規表示式匹配請求,則 nginx 會使用先前找到的最明確前綴位置。

請注意,所有類型的位置只會測試沒有引數的請求行中的 URI 部分。這樣做是因為查詢字串中的引數可以以多種方式給定,例如

/index.php?user=john&page=1
/index.php?page=1&user=john

此外,任何人都可以要求查詢字串中的任何內容

/index.php?page=1&something+else&user=john

現在,讓我們看看上述設定中的請求會如何處理

由 Igor Sysoev 撰寫
由 Brian Mercer 編輯