一、location的指令分為兩種匹配模式 :
- 普通字符串匹配
- 正則匹配
二、普通匹配包含三種格式:
修飾符 | 參考示例 | 說明 |
---|---|---|
無 | location /hello/world | 前綴匹配,不支持正則 |
= | location = /hello/world | 又叫精確匹配,不支持正則,匹配后既終止正則匹配又終止普通匹配 |
^~ | location ^~ /hello/world | 前綴匹配,不支持正則 ,匹配后不再進行正則匹配 |
三、正則匹配包含兩種格式:
修飾符 | 參考示例 | 說明 |
---|---|---|
~ | location ~ \.jpg$ | 區分大小寫的正則匹配,是包含匹配,而非前綴匹配 |
~* | location ~* \.jpg$ | 不區分大小寫的正則匹配,是包含匹配,而非前綴匹配 |
四、location匹配順序
五、關於location匹配的一些誤區
1、 location 的匹配順序是“先匹配正則,再匹配普通”。
矯正: location 的匹配順序其實是“先匹配普通,再“考慮”匹配正則”。注意這里的“考慮”是“可能”的意思,也就是說匹配完“普通 location ”后,有的時候需要繼續匹配“正則 location ”,有的時候則不需要繼續匹配“正則 location ”。兩種情況下,不需要繼續匹配正則 location :
( 1 )當普通 location 前面指定了“ ^~ ”,特別告訴 Nginx 本條普通 location 一旦匹配上,則不需要繼續正則匹配;
( 2 )當普通location 恰好嚴格匹配上,不是最大前綴匹配,則不再繼續匹配正則。
2、 location 的執行邏輯跟 location 的編輯順序無關。
矯正:這句話不全對,“普通 location ”的匹配規則是“最大前綴”,因此“普通 location ”的確與 location 編輯順序無關;但是“正則 location ”的匹配規則是“順序匹配,且只要匹配到第一個就停止后面的匹配”
總結一句話:“正則 location 匹配讓步普通 location 的嚴格精確匹配結果;但覆蓋普通 location 的最大前綴匹配結果”
六、舉個栗子
此處我用的是openresty版本的nginx,因此可以直接使用echo指令。如果是原生nginx,要使用echo指令的話,則需要自行編譯安裝echo-nginx-module,參考:https://github.com/openresty/echo-nginx-module#installation
server {
listen 80;
server_name localhost;
location / {
echo "first";
}
location ^~ /hello {
echo "111111-normal";
}
location /hello/world {
echo "222222-normal";
}
location ~ /hello/world {
echo "333333-regex";
}
}
訪問http://127.0.0.1/hello/world
的結果如下:
分析
在這個例子中,先進行普通匹配,按照最長匹配的原則,匹配到第三個location,然后這里的修飾符是非"="或"^~",則會繼續向下進行正則匹配,匹配到第四個location。
我們對上面的栗子進行稍加修改,將第三個和第四個location調換下順序,且將location /hello/world
修改為location ^~ /hello/world
如下:
server {
listen 80;
server_name localhost;
location / {
echo "first";
}
location ^~ /hello {
echo "111111-normal";
}
location ~ /hello/world {
echo "333333-regex";
}
location ^~ /hello/world {
echo "222222-normal";
}
}
這時候再訪問http://127.0.0.1/hello/world
的結果如下:
由此可以說明,匹配的順序是“先普通,再“考慮”正則”,而"="或"^~"這兩個修飾符會終止“考慮”正則。看到這里,是不是就清晰了很多呢。