Nginx路徑匹配規則詳解
本節要討論Nginx如何為一個請求選擇匹配的location進行處理。
如下配置文件:
server { listen 80 default_server; server_name itravel.smartcom.cc itravel-beta.huawei.com; client_max_body_size 8M; server_tokens off; root /data/web/itravel2.smartcom.cc/trunk/htdocs;error_page 404 /404.htm; error_page 500 502 503 504 /50x.htm; location / { #root /data/web/itravel2.smartcom.cc/trunk/htdocs; index index.php index.html index.htm; if (!-e $request_filename) { rewrite ^(.+)\.html$ $1.php last; } } location /static/js/ { #root /data/web/itravel2.smartcom.cc/trunk/htdocs; concat on; concat_types text/javascript; } location /static/css/ { #root /data/web/itravel2.smartcom.cc/trunk/htdocs; concat on; concat_types text/css; } location /api { } location ~/\.ht { } location ~ ^/~([^/]+)(/?.*)$ { } location ~ \.do$ { } location ~ \.(jpg|jpeg|gif|png|ico|css|tgz|gz|bz2|pdf|txt|tar|bmp|js|mov) { } location ~ /trip/ { } location /trip/ { } location ~ \.php$ { }
}</pre>
第一步:請求URI(路徑)規范化。
所謂規范化,就是先將URI中形如“%XX”的編碼字符進行解碼,再解析URI中的相對路徑“.”和“..”部分, 另外還可能會壓縮相鄰的兩個或多個斜線成為一個斜線。
舉例說明:若REQUEST_URI為//trip/t.php,則規范化后為/trip/t.php,Nginx將規范前的值存放在$request_uri中,而規范化后的值存放在$uri中。
其中,$request_uri和$uri為Nginx內嵌變量。
第二步:請求URI路徑匹配。
首先需要明確Nginx中將路徑匹配分為兩類:
前綴路徑匹配,即前綴字符串定義的路徑,如上配置文件中“/,/static/js/,/static/css/,/api,/trip/” 正則表達式路徑匹配,即使用正則表達式需要在路徑開始添加“~*”前綴 (不區分大小寫),或者“~”前綴(區分大小寫)。如上配置文件中“/\.ht,^/~([^/]+)(/?.*)$,\.do$,/trip/, \.php$,\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar||bmp|rtf|js|mov)”其次為了根據請求URI查找路徑,需要明確路徑匹配的順序:
Nginx首先檢查前綴字符串定義的路徑 (前綴路徑),在這些路徑中找到能最精確匹配請求URI的路徑。然后Nginx按在配置文件中的出現順序檢查正則表達式路徑,匹配上某個路徑后即停止匹配并使用該路徑的配置,否則使用最大前綴匹配的路徑的配置。
舉例說明:請求/trip/t.php,首先進行前綴路徑匹配,最精確的前綴路徑為/trip/,接下來進行正則表達式匹配,匹配到\.php$,從而進行location ~ \.php$ { }處理請求。反之若請求的是/trip/t.html,由于沒有正則表達式匹配到該URI,故匹配最精確的前綴路徑匹配,即進入location /trip/ { }處理請求。若想不論是請求/trip/t.php,還是/trip/t.html,都匹配到/trip/進行處理,則可以使用location ^~ /trip/ { },這樣Nginx就不會再檢查正則表達式了。
備注:
路徑可以嵌套,但有例外。
在不區分大小寫的操作系統(諸如Mac OS X和Cygwin)上,前綴匹配忽略大小寫(0.7.7)。但是,比較僅限于單字節的編碼區域(one-byte locale)。
正則表達式中可以包含匹配組(0.7.40),結果可以被后面的其他指令使用。
如果最大前綴匹配的路徑以“^~”開始,那么Nginx不再檢查正則表達式。在0.7.1到0.8.41的所有Nginx中,如果請求匹配的前綴字符串路徑并沒有“=”或“^~”前綴, 路徑查找過程仍然會停止,而不進行正則表達式匹配。而且,使用“=”前綴可以定義URI和路徑的精確匹配。如果發現匹配,則終止路徑查找。 比如,如果請求“/”出現頻繁,定義“location = /”可以提高這些請求的處理速度, 因為查找過程在第一次比較以后即結束。這樣的路徑明顯不可能包含嵌套路徑。
擴展閱讀: