爲了探究nginx的url配置規則,固然須要安裝nginx。我使用了vagrant建立了一個虛擬環境的ubuntu,經過apt-get安裝nginx。這樣就不會污染mac的軟件環境。經過vragrant再建立一個項目進行實驗。若是不瞭解vagrant的使用,能夠查看Vagrant 虛擬環境利器。html
/vagrant
目錄下建立了一個pro
用於項目的根目錄,同時配置nginx
的配置文件(/etc/nginx/sites-enabled/pro.conf
)nginx
☁ pro tree . ├── 403.html ├── 404.html ├── index.html 0 directories, 3 files
pro.conf
的配置以下,即監聽本機的80端口。web
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; }
上述的配置並無設置location
,可是配置了root /vagrant/pro
,訪問http://192.168.33.10/
將會返回/vagrant/pro/index.html
。正則表達式
nginx的url匹配模式很強大,同時使用很是靈活,尤爲是優先級的匹配,若是不尋找規律,不但很難掌握,並且容易犯暈。瞭解優先級以前,先看看匹配的配置語法,以及都有那些匹配模式。ubuntu
匹配的語法仍是很簡單的:服務器
location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... }
沒錯,就這麼多,實際寫在loacation
中大概是這樣的負載均衡
location = / { }
location [指令模式] url匹配模式 { }
指令模式指用於匹配的方式,即精確匹配,前綴匹配仍是正則匹配,固然這個是可選的,若是不寫,則退化成正常匹配或者全匹配。url匹配模式則須要匹配的url,能夠當作是web開發中的路由。下面就分別介紹指令模式和匹配模式。測試
=
指令用於精確字符匹配(模式),不能使用正則,區分大小寫。爲了直觀的觀察匹配命中的location,使用rewrite指令,用於轉發。目前只要理解命中了就重定向到rewrite後面的url便可。google
location = /demo { rewrite ^ http://google.com; }
上述的配置表示只有訪問 http://192.168.33.10/demo
這樣的url,才能跳轉到google的頁面。除此以外的任何地址都沒法訪問,那怕是訪問http://192.168.33.10/demo/
這個地址也不行。由於url匹配模式是/demo
。url
修改 location:
location = /demo$ { rewrite ^ http://google.com; }
熟悉正則的同窗初看會覺得/demo$
表示demo
結尾的url,其實否則,這裏的$
符號也是url的一部分,只有訪問http://192.168.33.10/demo$
這個地址才能跳轉。
^~
指令用於字符前綴匹配,和=
精確匹配同樣,也是用於字符肯定的匹配,不能使用正則且區分大小寫。和=
不一樣的在於,^~
指令下,訪問的url無需url匹配模式如出一轍,只須要其開頭前綴和url匹配模式同樣便可。
location ^~ /demo { rewrite ^ http://google.com; }
對於該模式(/demo
),訪問下列的地址都能匹配:
只須要以/demo
爲前綴開頭的url都能匹配。與該模式後的是否大小寫無關。
^~
不支持正則。模式/demo$
中的$
並不表明字符模式結束,而是一個是實實在在的$
,只有訪問/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
前綴匹配一般用於匹配文件夾,如配置靜態文件。
衆所周知,nginx的url功能強大,配置靈活。字符匹配中,支持正則和不支持正則徹底是兩個境界。前面的兩種方式都不能使用正則,未免讓人以爲nginx有點虛誇。
實際上,nginx支持正則匹配。所使用的指令是~
和~*
,前者表示使用正則,區分大小寫,後者表示使用正則,不區分大小寫。與前綴匹配同樣,正則匹配也是隻需匹配以url模式開頭的便可。
location ~ /[0-9]emo { rewrite ^ http://google.com; }
對於上述的模式,能夠匹配的url以下:
只要是以正則表達式/[0-9]emo
匹配的字符開頭的url,都能匹配。
使用~*
則不區分大小寫
location ~ /[0-9]EmO { rewrite ^ http://google.com; }
下面的都能匹配
正常匹配的指令爲空,即沒有指定匹配指令的即爲正常匹配。其形式相似 /XXX/YYY.ZZZ
正常匹配中的url匹配模式可使用正則,不區分大小寫。
location /demo { rewrite ^ http://google.com; }
上述模式指的是匹配/demo
的url,下面的都能匹配
正常匹配和前綴匹配的差異在於優先級。前綴的優先級高於正常匹配
全匹配與正常匹配同樣,沒有匹配指令,匹配的url模式僅一個斜槓/
location / { rewrite ^ http://google.com; }
全匹配也能夠配合 精確匹配和正則匹配一些指令,只不過這樣的設定意義不大。經過都會有一個默認的location,這個就是全匹配。
命名匹配指的是使用@
比綁定一個模式,相似變量替換的用法。
error_page 404 = @not_found location @not_found { rewrite http://google.com; }
上述的做用是若是訪問沒有匹配的url會觸發404指令,而後就匹配到@not_found
這個 location上。
nginx的匹配優先級遵循一個大原則和兩個小細節。
大原則是關於匹配模式的優先級:
精確匹配 > 前綴匹配 > 正則匹配 > 正常匹配 > 全匹配
小細節則是同一優先級中:
=
精確匹配的優先級最高,這與配置的前後順序無關
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
這個地址,而且還先命中,但是=
的優先級更高。
再把前綴匹配換成正則匹配
location ~ /demo{ rewrite ^ http://google.com; } location = /demo { rewrite ^ http://baidu.com; }
訪問結果仍然同樣。精確匹配的優先級最高。
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
因而可知,儘管也是正則匹配先命中規則,能夠優先級低,仍是讓步給前綴匹配。
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
的地址的時候,儘管前者位置在前,而且也匹配最長,但是大規則的優先級,仍是要先進行後面的正則匹配。小細節也必須讓步大規則。
location / { rewrite ^ http://google.com; } location /demo { rewrite ^ http://baidu.com; }
訪問結果
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
因而可知,全匹配的優先級最低。
同級的匹配須要注意兩個關鍵細節,是不是正則匹配,是不是最長匹配。
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,跳轉google.com;第二個鏈接二者都匹配,但是第二個location的匹配字符更長,所以跳轉了baidu.com。
把正常匹配換成前綴匹配的效果也同樣。
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最終會被命中。其實這個很好理解,匹配的字符越多,優先級越大嘛。可是爲何這個原則要特指非正則的匹配呢?
正則匹配不適用最大匹配的原則,本質緣由是由於正則一旦匹配了,就中止匹配其餘location,所以正則匹配與配置的前後順序有關。
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
已經匹配了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
因而可知,正則匹配與匹配最大長度無關,只與匹配的前後順序有關。
經過上述兩個模式的測試,咱們對兩個細節進行了倒序的推導。實際上使用記住兩個細節會比較簡單。判斷同級的優先級概括以下:
面對一個location,先判斷是不是正則匹配,若是是正則匹配,遇到匹配的模式,則命中。若是不是正則,則把匹配的模式放到一邊,繼續往下閱讀配置,閱讀完畢全部的匹配模式,查看哪種的匹配模式更長,則是最終命中的模式。
掌握nginx的location匹配優先級其實也不難,謹記一個原則兩個細節,媽媽不再用擔憂配錯url啦。
nginx的url配置是使用nginx最基本功能。nginx做爲服務器,它能夠接收請求,處理請求,都是基於客戶端url訪問。掌握url的配置要了解配置的幾個指令(=
,^~
)。熟悉每一個匹配模式的特色。
瞭解模式以後,對於優先級的斷定,只需記住一個大的規則和兩個細節,就能從容的應對了。
掌握url的配置以後,更重要的是在location域中作請求的處理。好比常見的靜態文件配置,請求轉發(rewrite),負載均衡等。
連接: