linux Nginx配置篇:location的匹配規則(附測試驗證過程)

討論location的匹配規則前,先弄明白location的分類:

只有兩類:正則location和普通location

~和~*爲正則location
=、^~、@和無任何前綴的都屬於普通location,另外,@是用作服務端內部的一種轉發行爲,很少用,在此不做討論。

先扔結論,或者說官網描述的匹配順序:
1.先普通,再正則
2.普通location之間的匹配順序:按最大前綴匹配
如location /a/{},location /a/b/ {},請求 http://a/b/c.html 匹配的是location /a/b/ {}
3.正則location之間的匹配順序:按配置文件中的物理順序匹配,只要匹配到一條正則,就不再考慮後面的
4.普通location與正則location之間的匹配結果選擇
普通location先匹配,匹配到了結果,只是一個臨時結果;會繼續正則location的匹配,如果匹配到正則,則用匹配到的正則結果;
如果沒有匹配到正則,則繼續用普通匹配的那個結果

綜上,常規的順序是匹配完普通location,還要繼續匹配正則location,但是,也可以告訴nginx,匹配到了普通location,就不要再搜索匹配正則location了,通過在普通location前面加上^~符號,^表示非,~表示正則,^~就是表示不要繼續匹配正則。

除了^~,=也可阻止nginx繼續匹配正則,區別在於^~依然遵循最大前綴匹配規則,而=是嚴格匹配

擴展:location /{} 和 location =/ {}的區別
/{}作爲普通匹配,是遵循最大前綴匹配原則的,所以,對於一個url,如果有更特殊合適的匹配,就選特殊合適的,如果沒有更特殊合適的匹配,也有/{}兜着,就像是默認配置一樣
=/ {} 遵循的是嚴格匹配規則,只能匹配到http://ip:port/,同時會停止搜索正則匹配。


接下來測試驗證。

1.先驗證第二條:普通location之間的匹配順序:按最大前綴匹配

nginx.conf配置:

        #普通location
        location  /a/b {
            return 666;
        }
        #普通location
        location /a/b/c {
            return 777;
        }

測試鏈接:http://192.168.88.38/a/b,http狀態碼爲666,符合預期。如圖(後面的測試可自行F12打開瀏覽器控制檯查看http狀態碼,不再截圖):


測試鏈接:http://192.168.88.38/a/b/c,http狀態碼爲777,匹配的是location /a/b/c {return 777;},符合預期。

2.驗證第三條:正則location之間的匹配順序:按配置文件中的物理順序匹配,只要匹配到一條正則,就不再考慮後面的

nginx.conf配置:

       location ~* /a {
            return 999;
        }
       #匹配a-z的任意一個字母
       location ~* ^/[a-z]$ {
            return 666;
        }

測試鏈接:http://192.168.88.38/a,http狀態碼999,匹配的是location ~*  /a {renturn 999;},符合預期。

將nginx.conf中的兩個正則匹配順序調換下:

        location ~* ^/[a-z]$ {
            return 666;
        }

        location ~* /a {
            return 999;
        }

測試鏈接:http://192.168.88.38/a,http狀態碼666,匹配的是location ~* ^/[a-z]$,符合預期。


3.驗證第4條,其實第4條就相當於是總結性的匹配順序了:

nginx.conf配置:

#普通location
location /a {
     return 666;
}
 #普通location
location  /a/b {
     return 777;
}
#正則location 
location ~* /a/b { 
     return 888;
}

測試鏈接:http://192.168.88.38/a,http狀態碼666,匹配到普通location,location /a {return 666;},符合預期。
測試鏈接:http://192.168.88.38/a/b,http狀態碼777,先進行普通location匹配,遵循最大前綴原則,匹配到location  /a/b {return 777; },但是,這只是一個臨時結果,因爲接下來還要繼續往下進行正則location匹配,匹配到 location ~* /a/b { return 888; },最終返回結果爲888。符合預期。
將正則location的規則改下:
        #普通location
        location /a {
            return 666;
        }
        #普通location
        location  /a/b {
            return 777;
        }
        #正則location
        location ~* /a/c {
            return 888;
         }

測試鏈接:http://192.168.88.38/a/b,http狀態碼777,匹配到location  /a/b {return 777; },並且因爲接下來沒有符合的正則location,所以最終返回爲777,符合預期。

綜上,location的匹配順序及結果取值都符合2,3,4點結論。
接下來再測試驗證普通location中的^~及=符號對於匹配搜索過程的阻斷效果,當然,別忘了這倆符號的真實作用。^~爲普通字符匹配,=爲精確匹配。
^~測試驗證nginx.conf配置:

         location /a {
            return 666;
        }
        #普通匹配
        location ^~ /a/b {
            return 777;
        }
        #正則location
        location ~* /a/b {
            return 888;
        }
測試鏈接:http://192.168.88.38/a/b,匹配到 location ^~ /a/b {return 777;}後,因爲使用了^~符號,不再繼續搜索正則location匹配,所以,雖然下面有符合條件的正則location,但是最終還是返回了777,符合預期。
=測試驗證nginx.conf配置:

        location /a {
            return 666;
        }
        #普通匹配
        location = /a/b {
            return 777;
        }
        #正則location
        location ~* /a/b {
            return 888;
        }
測試鏈接:http://192.168.88.38/a/b,匹配到 location = /a/b {return 777;}後,因爲使用了=符號,不再繼續搜索正則location匹配,最終返回777,符合預期。


另附上常用正則表達式:
. : 匹配除換行符外的任意字符
? : 重複0次或1次
+ : 重複1次或更多次
* : 重複0次或更多次
\d :匹配數字
^ : 匹配字符串的開始
$ : 匹配字符串的結束
{n} : 重複n次
{n,} : 重複n次或更多次
[c] : 匹配單個字符,如此處的字符 c
[a-z] : 匹配a-z小寫字母的任意一個
(a|b|c):匹配a或b或c

以上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章