Nginx的location規則:優先順序和路徑替換

王一洋發表於2019-02-01

Nginx是反向代理和負載均衡的首選工具,nginx的location配置有許多細節內容在網上不容易找到資料,或者解釋不清。本文對locaiton的常見特性進行介紹。

 

location的優先順序
locaiton有四種型別的匹配規則,分別為完全匹配(=)、字首普通匹配(^~)、正規表示式匹配(~或者~*)、普通匹配

規則

等號型別(=)的優先順序最高。一旦匹配成功,則不再查詢其他匹配項
字首普通匹配(^~)優先順序次之。不支援正規表示式。使用字首匹配,如果有多個location匹配的話,則使用表示式最長的那個
正規表示式型別(~ ~*)的優先順序次之。一旦匹配成功,則不再查詢其他匹配項
常規字串匹配,如果有多個location匹配的話,則使用表示式最長的那個
說明

先判斷精準命中,如果命中,立即返回結果並結束解析過程
若未結束,判斷字首普通命中,如果有多個命中,使用表示式“最長”的命中結果,結束解析過程
若未結束,繼續判斷正規表示式的匹配,按正規表示式順序為準,由上至下一旦匹配成功1個,立即返回結果,並結束解析過程
若未結束,繼續普通命中,普通命中和字首普通命中相似,順序無所謂,按照location表示式的長短來確定命中結果
“最長”命中

^~和普通命中,都是優先使用匹配最長的結果,示例如下:

location ^~ /a {
    root /;
}
location ^~ /aaa {
    root /aaa;
}


如果url為/aaa,則上面兩個location都匹配成功,但用於location ^~ /aaa較長,所以最終會以/aaa作為root

上例中如果是普通匹配(把location的^~去掉),結果也是一樣的

 

路徑替換
規則

配置proxy_pass時,可以實現URL路徑的部分替換。

proxy_pass的目標地址,預設不帶/,表示只代理域名,url和querystring部分不會變(把請求的path拼接到proxy_pass目標域名之後作為代理的URL)

如果在目標地址後增加/,則表示把path中location匹配成功的部分剪下掉之後再拼接到proxy_pass目標地址

比如請求 /a/b.html

location /a {
    proxy_pass http://server;
}
location /a {
    proxy_pass http://server/;
}


如上兩個匹配成功後,實際代理的目標url分別是

http://server/a/b.html (把/a/b.html拼接到http://server之後)

http://server/b.html (把/a/b.html的/a去掉之後,拼接到http://server/之後)

要求

注意的是,對於location為正規表示式的匹配,proxy_pass的目標地址不可以帶/

比如,如下配置會報錯:

location ~ /abc(.*) {
    proxy_pass   http://127.0.0.1/x;
}


正規表示式的替換

如果是正規表示式,想要實現proxy_pass的路徑替換,可以使用如下方式:

location ~ /abc(.*) { # 注意,使用這種方式,location內部不能包含if語句,否則proxy_pass不會生效
    proxy_pass   http://127.0.0.1/x$1;
}
如上可以把(.*)所匹配的內容拼接到http://127.0.0.1/abc之後,關於$1的使用,可以參考各種程式語言的正規表示式

另一種方法是:

location  /abc { # 這裡也可以是正則
    proxy_pass http://127.0.0.1/x$request_uri;
}

相關文章