編譯自:
http://nginx.org/en/docs/http/request_processing.htmlphp
目錄:
name-based 虛擬主機
對於未定義 server name 的訪問請求,如何防止其被處理
混合使用 name-based 虛擬主機和 IP-based 虛擬主機
一個簡單的 PHP 站點配置示例html
當一個訪問請求到達 nginx,nginx 會考慮選擇某一個 server 處理訪問請求。
咱們以一個包含三個 server 區塊的配置來說解: nginx
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; ... }
這三個虛擬主機均監聽於 *:80 端口。根據上面的配置,nginx 僅經過檢查請求首部中的
「HOST」 字段來決定讓哪一個虛擬主機處理訪問請求。若是該字段的值沒有匹配任何虛擬主機,
或者請求首部中沒有 「HOST」 字段,nginx 會將該請求路由到 *:80 端口的默認 server。
在上面的配置中,默認 server 是第一個 server —— 這是 nginx 的標準默認行爲。
咱們也能夠顯式指定一個默認 server,使用 listen 指令的 default_server 參數來指定,
例如:
正則表達式
server { listen 80 default_server; server_name example.net www.example.net; ... }
Note:
default_server 參數從 0.8.21 以後開始使用,以前是 default 參數。
要注意,默認 server 是監聽端口的一個屬性,不是 server name 的屬性。稍後將進一步描述這個問題。bash
若是但願禁止未定義 「Host」 請求首部的訪問請求,可設置一個 server 用於丟棄這樣的請求:服務器
server { listen 80; server_name ""; return 444; }
咱們在這裏將 server name 設置爲一個空字符串,它能匹配未攜帶 「Host」 請求首部的訪問請求,而且返回一個特殊的狀態碼 444 以關閉鏈接,444 不是標準的 nginx 狀態碼。測試
Note:
從 0.8.48 版開始,這個設置變成了 nginx 的默認設置,因此 server_name "" 可被刪去。
在更早的版本中,物理主機的主機名被設置爲 default server name。
spa
如今咱們看一個更復雜的配置案例,這裏有多個虛擬主機監聽於不一樣的地址: .net
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 區塊的 listen 指令
的參數進行對比,過濾掉不匹配的 server。而後 nginx 檢查訪問請求的 「Host」 請求首部,將它與剩下的 server 區塊中的 server_name 進行對比,看可否匹配。若是沒有匹配的 server,該請求將交給 default server 處理。code
例如,nginx 在 192.168.1.1:80 端口接收到對於 www.example.com 的訪問請求,由於在 192.168.1.1:80 端口沒有匹配的 server name,這個請求最後將被交給 192.168.1.1:80 端口的 default server 處理,也就是第一個server。
正如前面提到過,default server 是監聽端口的屬性,因此對於不一樣的監聽端口,能夠分別爲其定義不一樣的 default 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; ... }
192.168.1.1:80 端口的默認 server 是第二個 server;
192.168.1.2:80 端口的默認 server 是第三個 server。
最後咱們來看一個 PHP 站點的例子,看看 nginx 是如何選擇 location 處理請求的:
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 首先根據訪問請求的 URI 查找匹配的定義了 prefix 前綴的 location,並記住其中匹配的最長的前綴。在上面的例子中,定義了前綴的 location 只有一個,並且前綴爲 「/」,它是最短的前綴,能匹配全部請求。由於 「/」 前綴最短,因此這個 location 老是被做爲最後的備選。而後 nginx 開始檢查指定了正則表達式的 location,依照配置文件中的順序依次檢查是否與訪問請求的 URI 匹配,當找到第一個匹配的正則表達式,nginx 再也不繼續檢查後面的 location,nginx 將使用找到的第一個匹配正則表達式所對應的 location。若是沒有匹配的 正則表達式,nginx 將使用以前記住的擁有最長匹配前綴的 location。
要注意的是,全部類型的 location 僅測試請求的 URI 部分,不帶參數。由於在查詢字符串中的參數,可能以
幾種方式提供:
/index.php?user=john&page=1 /index.php?page=1&user=john
除此以外,在查詢字符串中,任何人能夠請求任何事情:
/index.php?page=1&something+else&user=john
如今咱們仔細研究一下根據上面的配置,nginx 將會如何處理訪問請求: