Nginx server 和 location 優先順序

Nginx是一個輕量形的 WEB 伺服器,功能很強大。

其中 server 和 location 可以有很多種的設定方式,也因此需要有個機制去選擇出到底該用哪一個。

這篇文章會說明 Nginx 選擇 server 和 location 的方法。



Server

當設定檔中有多個 server (...) 區塊,Nginx會怎麼選擇呢?
server的選擇相對比較簡單,在開始之前,要先了解Nginx怎麼編譯 Server 裡面的 listen 。
預設的 listen 通常是 :
listen 80 default_server;

但是一個完整的描述方法因該是:
listen IP:PORT;

而缺少的部分(不管是缺少IP還是Port號)Nginx會自動使用預設值補齊。
補齊的方式如下

缺少IP
如 listen 80;,Nginx會自動補0.0.0.0,變成 :
listen 0.0.0.0:80;

缺少Port
如 listen 10.1.1.1;,Nginx會自動補80 Port號,變成 :
listen 10.1.1.1:80;

兩個都缺
也就是沒有使用 listen ,nginx會自動補上 listen 0.0.0.0:80;

知道自動補齊的方法後,就可以開始討論選擇server的順序。


首先

Nginx會先檢查 IP:Port 的匹配。
選擇順序為
listen 有指定IP (如 10.1.1.1)
listen 無指定或使用0.0.0.0

第二

比對 server_name
當第一個IP:Port匹配檢查完後,發現有多個符合的結果,才會繼續比對。
選擇順序為
1. 完整比對到server_name,如 server_name www.example.com;
2. server_name前面有 * 符號,如 server_name *.example.com;
3. server_name後面有 * 符號,如 server_name www.*;
4. server_name是正規表示法,如 server_name ~www.example[1-3].com;
5. 全部的server_name都不匹配,此時Nginx會使用 listen 後面有 default_server字樣的
    如 :
    listen 80 default_server;
    server_name _;





Location

location的選擇比較複雜,如果再加上內部重新導向的功能,選擇上更加複雜。
這邊先說明單純的 location 選擇機制。
之所以使用機制這個說法,是因為在選擇的過程中並不像 server 這樣順序往下看。
下面的步驟中,出現 則使用 這個文字,代表Nginx不會再去看其它的 location ,而是選擇這個 location。
首先要介紹這邊會用到的 location種類 :
none - location後面沒有任何特殊符號,如 location /var/www {...}
= - location後面帶 = 符號,如 location = /var/www {...}
^~ - location後面帶 ^~ 符號,如 location ^~ /var/www {...}
~或~* - location後面帶 ~或~* 符號,如 location ~ /var/www {...}


稍為說明一下這些的功能:
none    - 最普通的寫法。
=     - 精確匹配,Client送進來的 URI必須完全一樣。
^~    - 排除正規表示法的匹配,功能等同 none ,可是使用的優先權高於正規表示法
~    - 正規表示法,區分大小寫
~*    - 正規表示法,不區分大小寫

(URI,以 "http://abc.com/image/logo.png" 這個為例,http:// 是 protocol,abc.com 是host_name或server name,/image/logo.png 這個就是 URI)
(在nginx內,$host_name沒有帶Port號,$server_name有帶Port號)


選擇機制為 :

1. 先搜索一次全部的none location。如 location /var/www {
2. location 後面使用 = 符號,並且精確匹配到,則使用。如 location = /var/www {
3. 匹配none locaiotn ,並且匹配到最長符合的項目。
    3.1這個 "最長符合的項目" 如果是 ^~,則使用。如 location ^~ /var/www {
    3.2  把這個 "最長符合的項目" 儲存起來。
           如 : location /var 和 location /var/www,location /var/www 會被儲存。
4. 尋找全部的正規表示法,第一個被匹配到的,則使用。因此正規表示法的上下順序很重要。
5. 全部的正規表示法都找不到,使用 剛剛儲存的"最長符合的項目" 的none location。
    如 : location /var/www {


location 範例說明 :

設定檔如下 :

location / {...}
location /image {...}
location = /image/server1/png {...}
location ^~ /image/server1 {...}
location ~* ^/image {...}
location ~* ^/image/server[1-3] {...}

1.
Client 送一個請求為,http://abc.com/image/server1/png/logo.png,這個請求的URI為 :
/image/server1/png/logo.png

依照機制 :
1. 找 = 符號的 location,location = /image/server1/png {...},但是這個沒有精確匹配到
2. 找最長符合,找到 location ^~ /image/server1 {...} ,因為是用 ^~ 符號,因此使用這個locaiotn。


2.
Client 送一個請求為,http://abc.com/image/server2/png/logo.png,這個請求的URI為 :
/image/server2/png/logo.png

依照機制 :
1. 找 = 符號的 location,location = /image/server1/png {...},但是這個沒有精確匹配到
2. 找最長符合,找到 location /image {...} ,因為沒有符號,因此先儲存。
3. 尋找正規表示的location,第一個匹配成功的是,location ~* ^/image {...},因此使用這個locaiotn。


3.
Client 送一個請求為,http://abc.com/www/index.html,這個請求的URI為 :
/www/index.html

依照機制 :
1. 找 = 符號的 location,location = /image/server1/png {...},但是這個沒有精確匹配到
2. 找最長符合,找到 location / {...} ,因為沒有符號,因此先儲存。
3. 尋找正規表示的location,但是找不到匹配的。
4. 使用原本的 "最長符合" 的location,location / {...}。




內部重新導向

所謂 "內部重新導向" 就是原本在某一個 location 內處理,因為設定的語法會跑到其它 location 或再一次進到相同的 location 進行處理。


會發生內部重新導向的狀況主要是有底下幾個語法 :
(執行的優先順序也會照這個順序進行)

  • rewrite
  • try_file
  • index
  • error_page



rewrite

rewrite後面可以再放置參數,如 rewrite ^/example/(.*)$ /$1 last;
會使rewrite造成不同的行為,其中會有以下的行為。
造成內部重新導向 :
不加參數
last

將請求返回給客戶端,讓客戶端再發送一個請求 :
(會造成客戶端的重新導向)
redriect
permanent

不進行內部重新導向
break


舉個例子
有一個請求是 /example/default
且設定檔如下

root /var/www/html;
location / {
    rewrite ^/example/(.*)$ /$1 last;
}

location /default {
    index index.html;
}

請求會先進到 "location /" 裡面,因為有使用 rewrite 語法,經過rewrite修改後的請求會變成  "/default"。
並且 rewrite 後面帶的參數是 last,因此Nginx會產生內部重新導向,跳到 "location /default",繼續進行請求的處理。


try_file

try_file可以讓Nginx進行一系列的檔案或資料夾的查找,並可在最後放置一個URI讓Nginx進行內部重新導向。
如 : try_file $uri $uri/ /default/error.html;


舉個例子
有一個請求是 /example/default
且設定檔如下

root /var/www/html;
location / {
    try_file $uri $uri/ /default/error.html;
}

location /default {
    index index.html;
}

請求會先進到 "location /" 裡面,並且依序尋找 :
"/var/www/html/example/default" 這個檔案
"/var/www/html/example/default/" 這個資料夾
當上面兩個都找不到時,重新導向到 /default/error.html


!!注意 : 當try_file和rewrite寫在同一個location時,會優先執行rewrite。

如以下設定,Nginx還是會先進行rewrite處理。

root /var/www/html;
location / {
    try_file $uri $uri/ /default/error.html;
    rewrite ^/example/(.*)$ /$1 last;
}

location /default {
    index index.html;
}


index

一般 index 是用做當請求的最後一個文字是 "/" 符號時,進行一系列檔案的查找。
如 "/example/default/" 或 最基本的 "/"。

index 也可以包含URI在裡面,如 index index.html /default/index.html,當找不到index.html,就會被內部重新導向到/default。


舉個例子
有一個請求是 /example/default/
且設定檔如下

root /var/www/html;
index index.html /default/index.htm;
location / {
    access_log /var/log/nginx/access.log;
}

location /default {
    access_log /var/log/default.log;
}

請求會先進到 "location /" 裡面,並且依序尋找 :
"/var/www/html/example/default/index.html" 這個檔案
"/var/www/html/default/index.htm" 這個檔案


error_page

這個功能是定義當出現錯誤代碼時,要導到那個頁面。

!!注意 : 404 錯誤回傳的網頁大小不能大於512K。


舉個例子
有一個請求是 /example/default
且設定檔如下

root /var/www/html;
index index.html /default/index.htm;
location / {
    error_page 404 /fail/page.html;
}

location /fail {
    access_log /var/log/404.log;
}

請求會先進到 "location /" 裡面,並且尋找 :
"/var/www/html/example/default" 這個檔案

當找不到時,Nginx會產生404錯誤碼,這時會觸發 error_page 404。
被重新導向到 "/fail/page.html"。

留言

發佈留言

此網誌的熱門文章

WPA_supplicant的設定方式

DOS指令 -- SET和變數