基本配置
為了探究nginx的url配置規(guī)則,當(dāng)然需要安裝nginx。我使用了vagrant創(chuàng)建了一個虛擬環(huán)境的ubuntu,通過apt-get安裝nginx类溢。這樣就不會污染mac的軟件環(huán)境。通過vragrant再創(chuàng)建一個項(xiàng)目進(jìn)行實(shí)驗(yàn)。如果不了解vagrant的使用闯冷,可以查看Vagrant 虛擬環(huán)境利器砂心。
/vagrant
目錄下創(chuàng)建了一個pro
用于項(xiàng)目的根目錄,同時(shí)配置nginx
的配置文件(/etc/nginx/sites-enabled/pro.conf
)
? pro tree
.
├── 403.html
├── 404.html
├── index.html
0 directories, 3 files
pro.conf
的配置如下蛇耀,即監(jiān)聽本機(jī)的80端口辩诞。
server {
listen 80 default_server;
server_name localhost;
access_log /var/log/nginx/pro/access.log;
error_log /var/log/nginx/pro/error.log;
error_page 404 /404.html;
root /vagrant/pro;
index index.html index.htm;
}
上述的配置并沒有設(shè)置location
,但是配置了root /vagrant/pro
纺涤,訪問http://192.168.33.10/
將會返回/vagrant/pro/index.html
译暂。
匹配模式
匹配語法
nginx的url匹配模式很強(qiáng)大,同時(shí)使用非常靈活撩炊,尤其是優(yōu)先級的匹配外永,如果不尋找規(guī)律,不但很難掌握拧咳,而且容易犯暈伯顶。了解優(yōu)先級之前,先看看匹配的配置語法呛踊,以及都有那些匹配模式。
匹配的語法還是很簡單的:
location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
沒錯啦撮,就這么多谭网,實(shí)際寫在loacation
中大概是這樣的
location = / {
}
location [指令模式] url匹配模式 {
}
指令模式指用于匹配的方式,即精確匹配,前綴匹配還是正則匹配赃春,當(dāng)然這個是可選的愉择,如果不寫,則退化成正常匹配或者全匹配织中。url匹配模式則需要匹配的url锥涕,可以看成是web開發(fā)中的路由。下面就分別介紹指令模式和匹配模式狭吼。
精確匹配
=
指令用于精確字符匹配(模式)层坠,不能使用正則,區(qū)分大小寫刁笙。為了直觀的觀察匹配命中的location破花,使用rewrite指令,用于轉(zhuǎn)發(fā)疲吸。目前只要理解命中了就重定向到rewrite后面的url即可座每。
location = /demo {
rewrite ^ http://google.com;
}
上述的配置表示只有訪問 http://192.168.33.10/demo
這樣的url,才能跳轉(zhuǎn)到google的頁面摘悴。除此之外的任何地址都無法訪問峭梳,那怕是訪問http://192.168.33.10/demo/
這個地址也不行。因?yàn)閡rl匹配模式是/demo
蹂喻。
修改 location:
location = /demo$ {
rewrite ^ http://google.com;
}
熟悉正則的同學(xué)初看會以為/demo$
表示demo
結(jié)尾的url葱椭,其實(shí)不然捂寿,這里的$
符號也是url的一部分,只有訪問http://192.168.33.10/demo$
這個地址才能跳轉(zhuǎn)挫以。
前綴匹配
^~
指令用于字符前綴匹配者蠕,和=
精確匹配一樣,也是用于字符確定的匹配掐松,不能使用正則且區(qū)分大小寫踱侣。和=
不同的在于,^~
指令下大磺,訪問的url無需url匹配模式一模一樣抡句,只需要其開頭前綴和url匹配模式一樣即可。
location ^~ /demo {
rewrite ^ http://google.com;
}
對于該模式(/demo
)杠愧,訪問下列的地址都能匹配:
- http://192.168.33.10/demo
- http://192.168.33.10/demo/
- http://192.168.33.10/demo/aaa
- http://192.168.33.10/demo/aaa/bbb
- http://192.168.33.10/demo/AAA
- http://192.168.33.10/demoaaa
- http://192.168.33.10/demo.aaa
只需要以/demo
為前綴開頭的url都能匹配待榔。與該模式后的是否大小寫無關(guān)。
^~
不支持正則流济。模式/demo$
中的$
并不代表字符模式結(jié)束锐锣,而是一個是實(shí)實(shí)在在的$
,只有訪問/demo$
開頭的url才能匹配绳瘟,http://192.168.33.10/demo
則不再匹配雕憔。
模式/[0-9]emo
也不代表正則中的http://192.168.33.10/0emo
、http://192.168.33.10/5emo
之類糖声,只有訪問以 /[0-9]emo
開頭url才行斤彼,例如http://192.168.33.10/[0-9]emo
或http://192.168.33.10/[0-9]emo/aaa
前綴匹配通常用于匹配文件夾,如配置靜態(tài)文件蘸泻。
正則匹配
眾所周知琉苇,nginx的url功能強(qiáng)大,配置靈活悦施。字符匹配中并扇,支持正則和不支持正則完全是兩個境界。前面的兩種方式都不能使用正則抡诞,未免讓人覺得nginx有點(diǎn)虛夸拜马。
實(shí)際上,nginx支持正則匹配沐绒。所使用的指令是~
和~*
俩莽,前者表示使用正則,區(qū)分大小寫乔遮,后者表示使用正則扮超,不區(qū)分大小寫。與前綴匹配一樣,正則匹配也是只需匹配以url模式開頭的即可出刷。
location ~ /[0-9]emo {
rewrite ^ http://google.com;
}
對于上述的模式璧疗,可以匹配的url如下:
- http://192.168.33.10/5emo
- http://192.168.33.10/9emo
- http://192.168.33.10/5emo/aaa
- http://192.168.33.10/5emo/AAA
- http://192.168.33.10/5emoaaa
只要是以正則表達(dá)式/[0-9]emo
匹配的字符開頭的url,都能匹配馁龟。
使用~*
則不區(qū)分大小寫
location ~ /[0-9]EmO {
rewrite ^ http://google.com;
}
下面的都能匹配
- http://192.168.33.10/5emo
- http://192.168.33.10/9Emo
- http://192.168.33.10/5emo/Aaa
- http://192.168.33.10/5eMoEaaa
正常匹配
正常匹配的指令為空崩侠,即沒有指定匹配指令的即為正常匹配。其形式類似 /XXX/YYY.ZZZ
正常匹配中的url匹配模式可以使用正則坷檩,不區(qū)分大小寫却音。
location /demo {
rewrite ^ http://google.com;
}
上述模式指的是匹配/demo
的url,下面的都能匹配
- http://192.168.33.10/demo
- http://192.168.33.10/demo/
- http://192.168.33.10/demo/aaa
- http://192.168.33.10/demo/aaa/bbb
- http://192.168.33.10/demo/AAA
- http://192.168.33.10/demoaaa
- http://192.168.33.10/demo.aaa
正常匹配和前綴匹配的差別在于優(yōu)先級矢炼。前綴的優(yōu)先級高于正常匹配
全匹配
全匹配與正常匹配一樣系瓢,沒有匹配指令,匹配的url模式僅一個斜杠/
location / {
rewrite ^ http://google.com;
}
全匹配也可以配合 精確匹配和正則匹配一些指令句灌,只不過這樣的設(shè)定意義不大夷陋。通過都會有一個默認(rèn)的location,這個就是全匹配胰锌。
命名匹配
命名匹配指的是使用@
比綁定一個模式骗绕,類似變量替換的用法。
error_page 404 = @not_found
location @not_found {
rewrite http://google.com;
}
上述的作用是如果訪問沒有匹配的url會觸發(fā)404指令资昧,然后就匹配到@not_found
這個 location上酬土。
匹配優(yōu)先級
nginx的匹配優(yōu)先級遵循一個大原則和兩個小細(xì)節(jié)。
大原則是關(guān)于匹配模式的優(yōu)先級:
精確匹配 > 前綴匹配 > 正則匹配 > 正常匹配 > 全匹配
小細(xì)節(jié)則是同一優(yōu)先級中:
- 細(xì)節(jié)一:正則匹配成功之后停止匹配榛搔,非正則匹配成功還會接著匹配诺凡。
- 細(xì)節(jié)二:在所有匹配成功的url中东揣,選取匹配度最大的url字符地址践惑。
不同級匹配模式優(yōu)先級原則
精確匹配 > 前綴匹配
=
精確匹配的優(yōu)先級最高,這與配置的先后順序無關(guān)
location ^~ /demo{
rewrite ^ http://google.com;
}
location = /demo {
rewrite ^ http://baidu.com;
}
訪問
http://192.168.33.10/demo -> baidu.com
http://192.168.33.10/demo/ggg -> google.com
盡管前綴匹配也能匹配/demo
這個地址嘶卧,并且還先命中尔觉,可是=
的優(yōu)先級更高。
再把前綴匹配換成正則匹配
location ~ /demo{
rewrite ^ http://google.com;
}
location = /demo {
rewrite ^ http://baidu.com;
}
訪問結(jié)果仍然一樣芥吟。精確匹配的優(yōu)先級最高侦铜。
前綴匹配 > 正則匹配
location ~ /[ad]emo{
rewrite ^ http://google.com;
}
location ^~ /demo {
rewrite ^ http://baidu.com;
}
上述兩個模式中,第一個使用正則匹配钟鸵,第二個使用前綴匹配钉稍,訪問效果如下
http://192.168.33.10/demo -> baidu.com
http://192.168.33.10/aemo -> google.com
由此可見,盡管也是正則匹配先命中規(guī)則棺耍,可以優(yōu)先級低贡未,還是讓步給前綴匹配。
正則匹配 > 正常匹配
location /demo/aa{
rewrite ^ http://google.com;
}
location ~ /[ad]emo {
rewrite ^ http://baidu.com;
}
http://192.168.33.10/demo/aa -> baidu.com
http://192.168.33.10/aemo/aa -> baidu.com
訪問/demo/aa
的地址的時(shí)候,盡管前者位置在前俊卤,并且也匹配最長嫩挤,可是大規(guī)則的優(yōu)先級,還是要先進(jìn)行后面的正則匹配消恍。小細(xì)節(jié)也必須讓步大規(guī)則岂昭。
正常匹配 > 全匹配
location / {
rewrite ^ http://google.com;
}
location /demo {
rewrite ^ http://baidu.com;
}
訪問結(jié)果
http://192.168.33.10 -> index.html
http://192.168.33.10/ -> google.comg
http://192.168.33.10/demo -> baidu.com
http://192.168.33.10/demo/aa -> baidu.com
由此可見,全匹配的優(yōu)先級最低狠怨。
同級匹配細(xì)節(jié)
同級的匹配需要注意兩個關(guān)鍵細(xì)節(jié)约啊,是否是正則匹配,是否是最長匹配取董。
非正則匹配
location /demo {
rewrite ^ http://google.com;
}
location /demo/aa {
rewrite ^ http://baidu.com;
}
訪問測試
http://192.168.33.10/demo -> google.com
http://192.168.33.10/demo/aa -> baidu.com
第一個連接只匹配了第一個location棍苹,跳轉(zhuǎn)google.com;第二個連接兩者都匹配茵汰,可是第二個location的匹配字符更長枢里,因此跳轉(zhuǎn)了baidu.com。
把正常匹配換成前綴匹配的效果也一樣蹂午。
location ^~ /demo {
rewrite ^ http://google.com;
}
location ^~ /demo/aa {
rewrite ^ http://baidu.com;
}
訪問結(jié)果如下:
http://192.168.33.10/demo -> google.com
http://192.168.33.10/demo/aa -> baidu.com
通過上面的測試栏豺,可見同級的非正則的匹配,匹配結(jié)果最長的location最終會被命中豆胸。其實(shí)這個很好理解奥洼,匹配的字符越多,優(yōu)先級越大嘛晚胡。但是為什么這個原則要特指非正則的匹配呢灵奖?
正則匹配
正則匹配不適用最大匹配的原則,本質(zhì)原因是因?yàn)檎齽t一旦匹配了估盘,就停止匹配其他location瓷患,因此正則匹配與配置的先后順序有關(guān)。
location ~ /demo {
rewrite ^ http://google.com;
}
location ~ /demo/aa {
rewrite ^ http://baidu.com;
}
http://192.168.33.10/demo/aa -> http://google.com
nginx開始匹配location的模式遣妥,其中/demo
已經(jīng)匹配了http://192.168.33.10/demo/aa
這個地址擅编,因此停止搜索匹配其他的location。
下面更改一下上述配置的先后順序:
location ~ /demo/aa {
rewrite ^ http://baidu.com;
}
location ~ /demo {
rewrite ^ http://google.com;
}
訪問測試:
http://192.168.33.10/demo/aa -> http://baidu.com
由此可見箫踩,正則匹配與匹配最大長度無關(guān)爱态,只與匹配的先后順序有關(guān)。
歸納
通過上述兩個模式的測試境钟,我們對兩個細(xì)節(jié)進(jìn)行了倒序的推導(dǎo)锦担。實(shí)際上使用記住兩個細(xì)節(jié)會比較簡單。判斷同級的優(yōu)先級歸納如下:
面對一個location慨削,先判斷是否是正則匹配洞渔,如果是正則匹配鱼的,遇到匹配的模式,則命中痘煤。如果不是正則凑阶,則把匹配的模式放到一邊,繼續(xù)往下閱讀配置衷快,閱讀完畢所有的匹配模式宙橱,查看哪一種的匹配模式更長,則是最終命中的模式蘸拔。
掌握nginx的location匹配優(yōu)先級其實(shí)也不難师郑,謹(jǐn)記一個原則兩個細(xì)節(jié),媽媽再也不用擔(dān)心配錯url啦调窍。
總結(jié)
nginx的url配置是使用nginx最基本功能宝冕。nginx作為服務(wù)器,它可以接收請求邓萨,處理請求地梨,都是基于客戶端url訪問。掌握url的配置要了解配置的幾個指令(=
缔恳,^~
)宝剖。熟悉每個匹配模式的特點(diǎn)。
了解模式之后歉甚,對于優(yōu)先級的判定万细,只需記住一個大的規(guī)則和兩個細(xì)節(jié),就能從容的應(yīng)對了纸泄。
掌握url的配置之后赖钞,更重要的是在location域中做請求的處理。比如常見的靜態(tài)文件配置聘裁,請求轉(zhuǎn)發(fā)(rewrite)雪营,負(fù)載均衡等。