<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
網上有很多討論 nginx location 順序的話題,得到的結論也基本一致,總結為:
=
^~
~
、~*
在很長的一段時間裡,我對上述的結論也一直深信不疑,甚至還將這個結論分享給其他小夥伴,直到在有一次設定時發現,請求 uri 明明是符合了字首匹配 ^~
規則,但 nginx 卻沒有使用,這讓我對上述結論產生了疑惑。後續通過調研、實踐後發現,上述結論可以說對,但也不對,是不是更疑惑了?沒關係,看完這篇文章你就知道我為什麼會這樣說了。
本篇文章會從以下五個方面來介紹 location
順序問題
location
是什麼location
的選項有哪些location
的匹配規則是什麼location
的應用規則是什麼話不多說,我們直接進入正題。
location
翻譯成中文就是定位,已經描述的比較清晰了,因為它的作用就是根據請求 uri 定位到某一個規則塊,然後在由該規則塊決定怎麼處理使用者的請求。
location
模組看起來挺簡單的,但真要自己寫,有時候就會覺得無從下手,我應該用 location /images
、 location ^~ /images
還是 location ~ /images
呢?我應該幫這個location
規則放在什麼位置呢?將規則放在最前面會影響已有的設定嗎?....上面說的問題,相信大部分同學都遇到過,想要徹底解決,就必須要了解 location
的處理邏輯,當然這也是本篇文章的目的所在。
location [ = | ~ | ~* | ^~ ] uri { ... }
按照匹配模式進行區分,location
後可以放置兩種型別的匹配規則,分別是字首字串(prefix string)和正規表示式(regular expression)。其中字首字串包括 =
、^~
以及不設定(也就是空串),而正規表示式只有 ~
和 ~*
。(這五種選項是經常看到的,還有一種不常用的 location @name { ... }
,並不在今天的討論範圍)
只有請求 uri 滿足 location
的規則,才有可能被應用,而對於不同的匹配模式,location
的匹配規則也是不同的
顧名思義,它表示從請求 uri 的開頭開始進行匹配,如果用 JavaScript 來描述的話,當 uri.indexOf(locationRule.uri) === 0
時表示滿足匹配規則,其中 uri
表示請求路徑,而 locationRule.uri
表示 location
設定的規則。
其中 =
選項比較特殊,它又叫做精準匹配,只有匹配規則與請求 uri 完全相等時才表示滿足條件,即只有當 uri === locationRule.uri
時才表示匹配成功。
其實就是通過正則匹配來驗證是否滿足規則,nginx 使用的是 Perl 相容正規表示式 (PCRE),網上可以找到很多驗證正規表示式的站點,這裡就不再展開了。但要注意,為了方便設定,nginx 進行了一些非標準的優化,例如,不必像在標準正規表示式中那樣跳脫 URL 中的正斜槓(/)等等。
而對於 ~
和 ~*
唯一的區別就是:~
區分大小寫,而 ~*
不區分大小寫。
下面,我們對 location
的選項進行一個簡單的總結
選項 | 匹配規則 | 範例 |
---|---|---|
= | 精準匹配 | location = /test {...} |
^~ | 從請求 uri 的開頭進行匹配 | location ^~ /test {...} |
[空串] | 從請求 uri 的開頭進行匹配 | location /test {...} |
~ | 區分大小寫的正則匹配 | location ~ /test {...} |
~* | 不區分大小寫的正則匹配 | location ~* /test {...} |
在瞭解完匹配規則後,我們來看下 nginx 是如何應用這些規則的,這就要說到 location
的順序問題了。
下面是根據實踐以檔案總結出來的 location
應用規則的邏輯:
server
塊中的 location
按照匹配模式分成兩個列表,分別為字首字串規則列表和正則匹配規則列表。=
),直接應用該規則,結束流程;否則找到匹配規則最長的那條記錄(記作 maxLenthStringPrefixRule
),繼續執行邏輯3;maxLenthStringPrefixRule
存在且匹配選項是 ^~
,應用該規則,結束流程;否則,執行邏輯4;location
,則執行邏輯5;maxLenthStringPrefixRule
存在,則應用該規則,流程結束;如果沒有則返回 404,同樣結束流程。如果上述描述看著很難理解,可以嘗試看下面的虛擬碼。
// 字串匹配的規則集合,按照在 .conf 檔案中的順序放置到該集合中 const stringPrefixRuleList = [...] // 正則匹配的規則集合,按照在 .conf 檔案中的順序放置到該集合中 const regularExpressionRuleList = [...] // 用於存放最長字串匹配的規則 let maxLenthStringPrefixRule; // 遍歷字串匹配的規則集合 for (let stringPrefixRule of stringPrefixRuleList) { // 符合匹配規則 if (stringPrefixRule.isMatched()) { // 匹配選項是精準匹配 if (stringPrefixRule.option === '=') { // 應用該規則,結束流程 applyRule(stringPrefixRule); return; } // 將最長匹配規則記錄下來,留到後面使用 if (!maxLenthStringPrefixRule || stringPrefixRule.uri.length > maxLenthStringPrefixRule.uri.length) { maxLenthStringPrefixRule = stringPrefixRule } } } // 如果最長匹配規則的選項是 ^~, 則應用該規則,流程結束 if (maxLenthStringPrefixRule && maxLenthStringPrefixRule.option === '^~') { applyRule(maxLenthStringPrefixRule); return; } // 遍歷正則匹配規則集合 for (let regularExpressionRule of regularExpressionRuleList) { // 如果有規則匹配上,則直接應用,流程結束 if (regularExpressionRule.isMatched()) { applyRule(regularExpressionRule); return; } } // 如果最長字串匹配的規則存在,則應用該規則 if (maxLenthStringPrefixRule) { applyRule(maxLenthStringPrefixRule); return; } // 404,規則未找到 throw new Error(404)
由此,我們可以得到幾個結論:
=
匹配規則後會終止搜尋,並直接使用該規則。所以,如果某個請求 url 頻繁發生,例如 /,我們可以在 nginx.conf
中新增 location = /
規則,這會加速這些請求的處理速度,因為在命中規則後會終止搜尋。^~
和空串的字首匹配,區別在於,如果命中 ^~
的規則,並且是最長字首匹配,就會終止搜尋正則匹配規則列表。location
規則,所以字首字串匹配和在檔案中的位置無關,但是和匹配長度有關。location
規則進行正則匹配時,命中一個就直接使用了,所以正則匹配和 location
規則在檔案中的位置有關從上面的理論篇中,大家應該能大致瞭解到 nginx 是如何命中 location
規則的,為了加深大家記憶,同時也為了能佐證理論是對的,我們來一些實踐吧。
我們的模板是這樣的,後面所有的實踐內容,都是放到兩個 rule section 之間。
server { listen 9001; location / { default_type text/html; return 200 'hello world'; } # ===== rule section ====== # ===== rule section ======
location /test { default_type text/html; return 200 '/test'; } location ~ /test { default_type text/html; return 200 '~ /test'; } location = /test { default_type text/html; return 200 '= /test'; }
我們在 nginx.conf
放置了 /test
、~ /test
、= /test
三個 location
規則,隨後在瀏覽器輸入 localhost:9001/test,發現輸出內容是 = /test
,符合我們的預期,=
選項的優先順序最高。
location ~ /test { default_type text/html; return 200 '~ /test'; } location ~ /test/*/demo { default_type text/html; return 200 '~ /test/*/demo'; }
隨後我們將 rule section 區塊替換成 ~ /test
和 ~ /test/*/demo
規則,在瀏覽器輸入 localhost:9001/test/xyz/demo,從正則角度來說,/test/xyz/demo
既滿足 /test
規則,又滿足 /test/*/demo
規則,但是由於 ~ /test
在檔案中位置靠前,所以優先被命中,理論上應該會輸出 ~ /test
,校驗後發現,確實是這樣。
location ^~ /test { default_type text/html; return 200 '^~ /test'; } location /test/more/andmore { default_type text/html; return 200 '/test/more/andmore'; } location ~ /test { default_type text/html; return 200 '~ /test'; }
將 section rule 區域替換成上述內容,然後在瀏覽器中輸入 localhost:9001/test/more/andmore,猜猜會發生什麼?
我們來一起分析下:
/test/more/andmore
,它不是 ^~
選項,所以會遍歷正則匹配規則~ /test
滿足匹配規則,直接應用該規則,所以會輸出 location ~ /test
規則塊的內容,也就是 ~ /test
我們再來試一下,在瀏覽器輸入 localhost:9001/test/more,會顯示什麼呢?
^~ /test
,是 ^~
選項,所以不用遍歷正則匹配規則列表,所以頁面會顯示 ^~ /test
。通過校驗後發現,上述分析的結果和實際顯示結果是一樣的。
上面幾個實踐都比較簡單,大家也可以嘗試各種組合,然後按照上面的分析步驟來檢驗下自己是不是真的理解了 location
。
看完上面的介紹,相信大家對 location
規則的處理邏輯都有一定的瞭解,也應該明白為什麼在文章開頭說曾經看到的結論對、也不對了。
如果要用對 location
順序進行總結的話,可以在原有的基礎上適當的進行一些擴充套件:
=
^~
,如果該字首匹配是最長字首匹配規則,則應用~
、~*
,和該規則在檔案中的順序有關,執行順序從上到下到此這篇關於nginx location 順序問題的文章就介紹到這了,更多相關nginx location 順序內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45