如何防止處理未定義主機名的請求 基於域名和IP混合的虛擬主機 一個簡單PHP站點配置 |
Nginx首先選定由哪個虛擬主機來處理請求。讓咱們從一個簡單的配置(其中所有3個虛擬主機都在端口*:80上監聽)開始:php
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」頭以決定該請求應由哪一個虛擬主機來處理。若是Host頭沒有匹配任意一個虛擬主機,或者請求中根本沒有包含Host頭,那nginx會將請求分發到定義在此端口上的默認虛擬主機。在以上配置中,第一個被列出的虛擬主機即nginx的默認虛擬主機——這是nginx的默認行爲。並且,能夠顯式地設置某個主機爲默認虛擬主機,即在"listen
"指令中設置"default_server
"參數:html
server { listen 80 default_server; server_name example.net www.example.net; ... }
"default_server
"參數從0.8.21版開始可用。在以前的版本中,應該使用"default
"參數代替。
請注意"default_server
"是監聽端口的屬性,而不是主機名的屬性。後面會對此有更多介紹。nginx
若是不容許請求中缺乏「Host」頭,能夠定義以下主機,丟棄這些請求:web
server { listen 80; server_name ""; return 444; }
在這裏,咱們設置主機名爲空字符串以匹配未定義「Host」頭的請求,並且返回了一個nginx特有的,非http標準的返回碼444,它能夠用來關閉鏈接。正則表達式
從0.8.48版本開始,這已成爲主機名的默認設置,因此能夠省略
server_name ""
。而以前的版本使用機器的
hostname做爲主機名的默認值。
下面讓咱們來看一個複雜點的配置,在這個配置裏,有幾個虛擬主機在不一樣的地址上監聽:服務器
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指令配置。接着nginx繼續測試請求的Host頭是否匹配這個server塊中的某個server_name的值。若是主機名沒有找到,nginx將把這個請求交給默認虛擬主機處理。例如,一個從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怎樣爲一個請求選擇location來處理:spa
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使用前綴匹配找出最準確的location,這一步nginx會忽略location在配置文件出現的順序。上面的配置中,惟一的前綴匹配location是"/
",並且由於它能夠匹配任意的請求,因此被做爲最後一個選擇。接着,nginx繼續按照配置中的順序依次匹配正則表達式的location,匹配到第一個正則表達式後中止搜索。匹配到的location將被使用。若是沒有匹配到正則表達式的location,則使用剛剛找到的最準確的前綴匹配的location。.net
請注意全部location匹配測試只使用請求的URI部分,而不使用參數部分。這是由於寫參數的方法不少,好比:
/index.php?user=john&page=1 /index.php?page=1&user=john
除此之外,任何人在請求串中均可以隨意添加字符串:
/index.php?page=1&something+else&user=john
如今讓咱們來看使用上面的配置,請求是怎樣被處理的:
/logo.gif
"首先匹配上location "/
",而後匹配上正則表達式"\.(gif|jpg|png)$
"。所以,它將被後者處理。根據"root /data/www
"指令,nginx將請求映射到文件/data/www/logo.gif
",併發送這個文件到客戶端。/index.php
"首先也匹配上location "/
",而後匹配上正則表達式"\.(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
"僅能匹配上location "/
",所以,它將使用此location進行處理。根據"root /data/www
"指令,nginx將請求映射到文件"/data/www/about.html
",併發送這個文件到客戶端。/
"的處理更爲複雜。它僅能匹配上location "/
",所以,它將使用此location進行處理。而後,index指令使用它的參數和"root /data/www
"指令所組成的文件路徑來檢測對應的文件是否存在。若是文件/data/www/index.html
不存在,而/data/www/index.php
存在,此指令將執行一次內部重定向到"/index.php
",接着nginx將從新尋找匹配"/index.php
"的location,就好像此次請求是從客戶端發過來同樣。正如咱們以前看到的那樣,這個重定向的請求最終交給FastCGI服務器來處理。做者: Igor Sysoev編輯: Brian Mercer翻譯: Jinglong & cfsego |