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
現在,讓我們看看上述設定中的請求會如何處理
- 請求「
/logo.gif
」首先由前綴位置「/
」匹配,然後由正規表示式「\.(gif|jpg|png)$
」匹配,因此,它由後者的位置處理。使用指令「root /data/www
」,該請求會對應到檔案/data/www/logo.gif
,並且該檔案會被傳送給用戶端。 - 請求「
/index.php
」也首先由前綴位置「/
」匹配,然後由正規表示式「\.(php)$
」匹配。因此,它由後者的位置處理,並且請求會被傳遞到監聽 localhost:9000 的 FastCGI 伺服器。fastcgi_param 指令將 FastCGI 參數SCRIPT_FILENAME
設定為「/data/www/index.php
」,並且 FastCGI 伺服器會執行該檔案。變數$document_root
等於 root 指令的值,而變數$fastcgi_script_name
等於請求 URI,即「/index.php
」。 - 請求「
/about.html
」僅由前綴位置「/
」匹配,因此,它在此位置處理。使用指令「root /data/www
」,該請求會對應到檔案/data/www/about.html
,並且該檔案會被傳送給用戶端。 - 處理請求「
/
」更複雜。它僅由前綴位置「/
」匹配,因此,它在此位置處理。然後,index 指令會根據其參數和「root /data/www
」指令測試索引檔案是否存在。如果檔案/data/www/index.html
不存在,並且檔案/data/www/index.php
存在,則該指令會內部重新導向到「/index.php
」,並且 nginx 會重新搜尋位置,就像請求是由用戶端傳送的一樣。如我們之前所見,重新導向的請求最終會由 FastCGI 伺服器處理。
由 Igor Sysoev 撰寫 由 Brian Mercer 編輯 |