開篇
?最近剛好在極客世界地訂閱了關(guān)于nginx的課程,也對(duì)公司通過nginx打點(diǎn)日志的實(shí)現(xiàn)比較感興趣,所以抽空研究下nginx的location規(guī)則匹配邏輯。
?這篇文章轉(zhuǎn)自互聯(lián)網(wǎng),在文章末尾注明了出處了,之所以轉(zhuǎn)載是因?yàn)檫@篇文章講解的比較清晰,適合像我這樣的入門小白學(xué)習(xí)。有興趣的可以參考著學(xué)習(xí)。
概念
location
syntax: location [=|~|~*|^~|@] /uri/ { … }
default: no
context: server
This directive allows different configurations depending on the URI.
譯文:
1 、different configurations depending on the URI 說的就是語法格式:location [= | ~ | ~* | ^~ | @] /uri/ { … } ,依據(jù)不同的前綴“= ”,“^~ ”,“~ ”,“~* ”和不帶任何前綴的(因?yàn)閇A] 表示可選,可以不要的),表達(dá)不同的含義, 簡單的說盡管location 的/uri/ 配置一樣,但前綴不一樣,表達(dá)的是不同的指令含義。
2 、查詢字符串不在URI范圍內(nèi)。例如:/films.htm?fid=123 的URI 是/films.htm 。
It can be configured using both literal strings and regular expressions. To use regular expressions, you must use a prefix:
- 1、“~” for case sensitive matching
- 2、“~*” for case insensitive matching
譯文:
1、上文講到location /uri/ 可通過使用不同的前綴,表達(dá)不同的含義。對(duì)這些不同前綴分下類就2 大類:正則location(英文說法是location using regular expressions)和 普通location(英文說法是location using literal strings )。
2、其中~和~*前綴表示正則location ,~區(qū)分大小寫,~不區(qū)分大小寫;其他前綴(包括:=,^~和@*)和無任何前綴的都屬于普通location 。
To determine which location directive matches a particular query, the literal strings are checked first.
譯文:
1、對(duì)于一個(gè)特定的 HTTP 請(qǐng)求(a particular query), nginx 應(yīng)該匹配哪個(gè) location 塊的指令呢(注意:我們?cè)?nginx.conf 配置文件里面一般會(huì)定義多個(gè) location 的)?
2、匹配 規(guī)則是:先匹配普通location (再匹配正則表達(dá)式)。注意:官方文檔這句話就明確說了,先普通location ,而不是有些同學(xué)的誤區(qū)“先匹配正則location ”。
Literal strings match the beginning portion of the query – the most specific match will be used.
譯文:
1、前面說了普通location與正則location之間的匹配規(guī)則是:先匹配普通location ,再匹配正則location 。那么,普通location 內(nèi)部(普通location 與普通location )是如何匹配的呢?簡單的說:最大前綴匹配。
2、原文:(1)、match the beginning portion of the query (說的是匹配URI 的前綴部分beginning portion ); (2) 、the most specific match will be used (因?yàn)閘ocation 不是“嚴(yán)格匹配”,而是“前綴匹配”,就會(huì)產(chǎn)生一個(gè)HTTP 請(qǐng)求,可以“前綴匹配”到多個(gè)普通location ,例如:location /prefix/mid/ {} 和location /prefix/ {} ,對(duì)于HTTP 請(qǐng)求/prefix/mid/t.html ,前綴匹配的話兩個(gè)location 都滿足,選哪個(gè)?原則是:the most specific match ,于是選的是location /prefix/mid/ {})。
Afterwards, regular expressions are checked in the order defined in the configuration file. The first regular expression to match the query will stop the search.
譯文:
1、這段話說的第一層意思是:“Afterwards, regular expressions are checked ”, 意思是普通location 先匹配,而且選擇了最大前綴匹配后,不能就停止后面的匹配,最大前綴匹配只是一個(gè)臨時(shí)的結(jié)果,nginx 還需要繼續(xù)檢查正則location(但至于最終才能普通location 的最大前綴匹配,還是正則location 的匹配,截止當(dāng)前的內(nèi)容還沒講,但后面會(huì)講)。
2、這段話說的第二層意思是“regular expressions are checked in the order defined in the configuration file. The first regular expression to match the query will stop the search. ”,意思是說“正則location ”與“正則location”內(nèi)部的匹配規(guī)則是:按照正則location 在配置文件中的物理順序(編輯順序)匹配的(這句話就說明location 并不是一定跟順序無關(guān),只是普通location 與順序無關(guān),正則location 還是與順序有關(guān)的),并且只要匹配到一條正則location ,就不再考慮后面的(這與“普通location ”與“正則location ”之間的規(guī)則不一樣。
3、“普通location ”與“正則location ”之間的規(guī)則是:選擇出“普通location ”的最大前綴匹配結(jié)果后,還需要繼續(xù)搜索正則location )。
If no regular expression matches are found, the result from the literal string search is used.
譯文:
- 1、這句話回答了“普通location ”的最大前綴匹配結(jié)果與繼續(xù)搜索的“正則location ”匹配結(jié)果的決策關(guān)系。如果繼續(xù)搜索的“正則location ”也有匹配上的,那么“正則location”覆蓋“普通location ”的最大前綴匹配(因?yàn)橛羞@個(gè)覆蓋關(guān)系,所以造成有些同學(xué)以為正則location 先于普通location 執(zhí)行的錯(cuò)誤理解);但是如果“正則location ”沒有能匹配上,那么就用“普通location ”的最大前綴匹配結(jié)果。
It is possible to disable regular expression checks after literal string matching by using “^~” prefix.If the most specific match literal location has this prefix: regular expressions aren’t checked.
譯文:
- 1、通常的規(guī)則是,匹配完了“普通location ”指令,還需要繼續(xù)匹配“正則location ”,但是你也可以告訴Nginx :匹配到了“普通location ”后,不再需要繼續(xù)匹配“正則location ”了,要做到這一點(diǎn)只要在“普通location ”前面加上“^~ ”符號(hào)(^ 表示“非”,~ 表示“正則”,字符意思是:不要繼續(xù)匹配正則)。
By using the “=” prefix we define the exact match between request URI and location. When matched search stops immediately. E.g., if the request “/” occurs frequently, using “l(fā)ocation = /” will speed up processing of this request a bit as search will stop after first comparison.
譯文:
1、除了上文的“^~ ”可以阻止繼續(xù)搜索正則location 外,你還可以加“= ”。那么如果“^~ ”和“= ”都能阻止繼續(xù)搜索正則location 的話,那它們之間有什么區(qū)別呢?區(qū)別很簡單,共同點(diǎn)是它們都能阻止繼續(xù)搜索正則location ,不同點(diǎn)是“^~ ”依然遵守“最大前綴”匹配規(guī)則,然而“= ”不是“最大前綴”,而是必須是嚴(yán)格匹配(exact match )。
2、這里順便講下“l(fā)ocation / {} ”和“l(fā)ocation = / {} ”的區(qū)別,“l(fā)ocation / {} ”遵守普通location 的最大前綴匹配,由于任何URI 都必然以“/ ”根開頭,所以對(duì)于一個(gè)URI ,如果有更specific 的匹配,那自然是選這個(gè)更specific 的,如果沒有,“/ ”一定能為這個(gè)URI 墊背(至少能匹配到“/ ”),也就是說“l(fā)ocation / {} ”有點(diǎn)默認(rèn)配置的味道,其他更specific的配置能覆蓋overwrite 這個(gè)默認(rèn)配置(這也是為什么我們總能看到location / {} 這個(gè)配置的一個(gè)很重要的原因)。而“l(fā)ocation = / {} ”遵守的是“嚴(yán)格精確匹配exact match ”,也就是只能匹配 http://host:port/ 請(qǐng)求,同時(shí)會(huì)禁止繼續(xù)搜索正則location 。因此如果我們只想對(duì)“GET / ”請(qǐng)求配置作用指令,那么我們可以選“l(fā)ocation = / {} ”這樣能減少正則location 的搜索,因此效率比“l(fā)ocation / {}” 高(注:前提是我們的目的僅僅只想對(duì)“GET / ”起作用)。
On exact match with literal location without “=” or “^~” prefixes search is also immediately terminated.
譯文:
1、前面我們說了,普通location 匹配完后,還會(huì)繼續(xù)匹配正則location ;但是nginx 允許你阻止這種行為,方法很簡單,只需要在普通location 前加“^~ ”或“= ”。但其實(shí)還有一種“隱含”的方式來阻止正則location 的搜索,這種隱含的方式就是:當(dāng)“最大前綴”匹配恰好就是一個(gè)“嚴(yán)格精確(exact match )”匹配,照樣會(huì)停止后面的搜索。原文字面意思是:只要遇到“精確匹配exact match ”,即使普通location 沒有帶“= ”或“^~ ”前綴,也一樣會(huì)終止后面的匹配。
2、先舉例解釋下,后面例題會(huì)用實(shí)踐告訴大家。假設(shè)當(dāng)前配置是:location /exact/match/test.html { 配置指令塊1},location /prefix/ { 配置指令塊2} 和 location ~ .html$ { 配置指令塊3} ,如果我們請(qǐng)求 GET /prefix/index.html ,則會(huì)被匹配到指令塊3 ,因?yàn)槠胀╨ocation /prefix/ 依據(jù)最大匹配原則能匹配當(dāng)前請(qǐng)求,但是會(huì)被后面的正則location 覆蓋;當(dāng)請(qǐng)求GET /exact/match/test.html ,會(huì)匹配到指令塊1 ,因?yàn)檫@個(gè)是普通location 的exact match ,會(huì)禁止繼續(xù)搜索正則location 。
To summarize, the order in which directives are checked is as follows:
- Directives with the “=” prefix that match the query exactly. If found, searching stops.
- All remaining directives with conventional strings. If this match used the “^~” prefix, searching stops.
- Regular expressions, in the order they are defined in the configuration file.
- If #3 yielded a match, that result is used. Otherwise, the match from #2 is used.
這個(gè)順序沒必要再過多解釋了。但我想用自己的話概括下上面的意思“正則 location 匹配讓步普通location 的嚴(yán)格精確匹配結(jié)果;但覆蓋普通 location 的最大前綴匹配結(jié)果”。