[轉]簡明 Nginx Location Url 配置筆記

基本配置

爲了探究nginx的url配置規則,當然需要安裝nginx。我使用了vagrant創建了一個虛擬環境的ubuntu,通過apt-get安裝nginx。這樣就不會污染mac的軟件環境。通過vragrant再創建一個項目進行實驗。如果不瞭解vagrant的使用,可以查看Vagrant 虛擬環境利器

/vagrant目錄下創建了一個pro用於項目的根目錄,同時配置nginx的配置文件(/etc/nginx/sites-enabled/pro.conf)

☁  pro  tree.├── 403.html├── 404.html├── index.html 0 directories, 3 files

pro.conf的配置如下,即監聽本機的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;  } 

上述的配置並沒有設置location,但是配置了root /vagrant/pro,訪問http://192.168.33.10/將會返回/vagrant/pro/index.html

匹配模式

匹配語法

nginx的url匹配模式很強大,同時使用非常靈活,尤其是優先級的匹配,如果不尋找規律,不但很難掌握,而且容易犯暈。瞭解優先級之前,先看看匹配的配置語法,以及都有那些匹配模式。

匹配的語法還是很簡單的:

location [ = | ~ | ~* | ^~ ] uri { ... }location @name { ... }

沒錯,就這麼多,實際寫在loacation中大概是這樣的

location = / {    }
location  [指令模式] url匹配模式 {    }

指令模式指用於匹配的方式,即精確匹配,前綴匹配還是正則匹配,當然這個是可選的,如果不寫,則退化成正常匹配或者全匹配。url匹配模式則需要匹配的url,可以看成是web開發中的路由。下面就分別介紹指令模式和匹配模式。

精確匹配

=指令用於精確字符匹配(模式),不能使用正則,區分大小寫。爲了直觀的觀察匹配命中的location,使用rewrite指令,用於轉發。目前只要理解命中了就重定向到rewrite後面的url即可。

location = /demo {    rewrite ^ http://google.com;}

上述的配置表示只有訪問 http://192.168.33.10/demo 這樣的url,才能跳轉到google的頁面。除此之外的任何地址都無法訪問,那怕是訪問http://192.168.33.10/demo/這個地址也不行。因爲url匹配模式是/demo

修改 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/0emohttp://192.168.33.10/5emo之類,只有訪問以 /[0-9]emo開頭url纔行,例如http://192.168.33.10/[0-9]emohttp://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的匹配優先級遵循一個大原則兩個小細節

大原則是關於匹配模式的優先級:

精確匹配  >  前綴匹配  >  正則匹配  > 正常匹配  > 全匹配

小細節則是同一優先級中:

  • 細節一:正則匹配成功之後停止匹配,非正則匹配成功還會接着匹配。
  • 細節二:在所有匹配成功的url中,選取匹配度最大的url字符地址。

不同級匹配模式優先級原則

精確匹配 > 前綴匹配

=精確匹配的優先級最高,這與配置的先後順序無關

location ^~ /demo{    rewrite ^ http://google.com;} location = /demo {    rewrite ^ http://baidu.com;} 

訪問

http://192.168.33.10/demo    -> baidu.comhttp://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.comhttp://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.htmlhttp://192.168.33.10/         -> google.comghttp://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.comhttp://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.comhttp://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),負載均衡

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章