Nginx 的 location 語法爲:
location [ = | ~ | ~* | ^~ ] uri { ... }
uri 中的 %xx
內容會被解碼後進行匹配。
匹配修飾符雖然有四種,但其實匹配算法只有兩種:前綴匹配 和 正則表達式匹配。
以 ~
開頭的是正則匹配,帶不帶 *
的區別僅在於是否區分大小寫——帶星號不區分。
類似 location /
這樣沒有修飾符的是前綴匹配。
正則表達式的 uri 裏可以寫正則表達式,而前綴匹配的 uri 裏就是普通的路徑。
對於一個 uri,匹配 location 的邏輯是:
- 先進行前綴匹配,找到匹配前綴最長的一個 location,記爲 foo,但並不使用
- 然後進行正則匹配,按配置文件內的書寫順序輪流匹配,若匹配成功就 break,並使用該正則匹配;若全部都匹配不上,就使用第一步裏的 foo
最後解釋 ^~
和 =
的作用。這兩個修飾符是用來修改匹配邏輯的。
- 如果在第一步找到的最長 location(foo)使用了
^~
修飾符,那麼跳過第二步,直接使用 foo =
表示嚴格相等,如果在第一步中成功匹配了此類規則,則直接跳過接下來的全部步驟,直接使用此 location,就是連最長匹配也不找了(實際這就是最長匹配)
其實從規則來看,對於精確匹配的需求,^~
完全可以實現,那麼爲什麼還需要一個 =
呢?比如考慮下面的例子:假如我有一個主頁文件 /index.html
,那麼我寫 ^~ /index.html
和 = /index.html
其實最終效果是一樣的。
官方文檔對等號的解釋是:對於訪問佔比特別大的路徑來說,用 =
匹配速度會更快些。
至於爲什麼快,可能得去看下源碼了。大家也可以自己思考一下步驟一,如果讓你來寫你會怎麼實現。在此實現的基礎上再考慮精確匹配的需求,能不能達到效率最優。如果不能,那麼 =
這個修飾符的存在就是合理的。