Nginx Location匹配規則

本文非徹底原創, 更多的是將相關資料進行整理html

Last-Modified: 2019年5月10日15:28:29linux

參考連接

規則語法

語法 匹配規則
普通匹配(遵循最大前綴匹配規則, 優先度比正則低)
= 精確(嚴格)匹配, 優先度最高
後續再也不匹配正則
^~ 非正則匹配(依然遵循最大前綴匹配規則)
後續再也不匹配正則
~ 表示區分大小寫的正則匹配
~* 表示不區分大小寫的正則匹配
/ 通用匹配,任何請求都會匹配到(本質上等同於語法 )

!~!~* 分別爲區分大小寫不匹配及不區分大小寫不匹配 的正則, 可是是用於條件判斷的時候(即 if 語句)nginx

if ($host !~* "^www\.") {
    # ...
}

匹配簡單來講:正則表達式

  1. 優先匹配 = 精確匹配, 若未匹配到則轉下一步驟
  2. 依照最大前綴匹配規則, 先匹配普通規則( , ^~)

    若最終匹配到 ^~, 則使用瀏覽器

    若匹配到 或 未匹配到, 則轉下一步驟(當前匹配結果暫時保存)測試

  3. 按照物理存儲順序, 若匹配到任意一條正則, 立刻使用(無視後面正則)

    若未匹配到任意正則, 則使用步驟2中匹配到普通正則url

location 分類

只有兩類:正則location和普通locationspa

~~* 爲正則location
=^~@和無任何前綴的都屬於普通location,另外,@是用做服務端內部的一種轉發行爲,不多用,在此不作討論。.net

匹配順序:

  1. 先普通,再正則
  2. 普通location之間的匹配順序:按最大前綴匹配
    location /a/{}location /a/b/ {},請求 http://a/b/c.html 匹配的是 location /a/b/ {}
  3. 正則location之間的匹配順序:按配置文件中的物理順序匹配,只要匹配到一條正則,就再也不考慮後面的
  4. 若普通location匹配到 精確匹配= 或 非正則匹配 ^~, 則再也不進行後續的正則匹配
  5. 普通location與正則location之間的匹配結果選擇code

    1. 普通location先匹配,匹配到告終果,只是一個臨時結果;
    2. 會繼續正則location的匹配,

      1. 若是匹配到正則,則用匹配到的正則結果;
      2. 若是沒有匹配到正則,則繼續用普通匹配的那個結果

綜上,常規的順序是匹配完普通location,還要繼續匹配正則location,可是,也能夠告訴nginx,匹配到了普通location,就不要再搜索匹配正則location了,經過在普通location前面加上^~符號,^表示非,~表示正則,^~就是表示不要繼續匹配正則。

除了^~=也可阻止nginx繼續匹配正則,區別在於^~依然遵循最大前綴匹配規則,而=是嚴格匹配

擴展

location / {}location =/ {}的區別

/ {}做爲普通匹配,是遵循最大前綴匹配原則的,因此,對於一個url,若是有更特殊合適的匹配,就選特殊合適的,若是沒有更特殊合適的匹配,也有 / {}兜着,就像是默認配置同樣

=/ {} 遵循的是嚴格匹配規則,只能匹配到 http://ip:port/,同時會中止搜索正則匹配。

測試

接下來測試驗證。

1.先驗證第二條:普通location之間的匹配順序:按最大前綴匹配

nginx.conf配置:

#普通location
location  /a/b {
    return 666;
}
#普通location
location /a/b/c {
    return 777;
}

測試連接:http://192.168.88.38/a/b,http狀態碼爲666,符合預期。如圖(後面的測試可自行F12打開瀏覽器控制檯查看http狀態碼,再也不截圖):

測試連接:http://192.168.88.38/a/b/c,http狀態碼爲777,匹配的是location /a/b/c {return 777;},符合預期。

2.驗證第三條:正則location之間的匹配順序:按配置文件中的物理順序匹配,只要匹配到一條正則,就再也不考慮後面的

nginx.conf配置:

location ~* /a {
    return 999;
}
#匹配a-z的任意一個字母
location ~* ^/[a-z]$ {
    return 666;
}

測試連接:http://192.168.88.38/a,http狀態碼999,匹配的是location ~* /a {renturn 999;},符合預期。
將nginx.conf中的兩個正則匹配順序調換下:

location ~* ^/[a-z]$ {
    return 666;
}

location ~* /a {
    return 999;
}

測試連接:http://192.168.88.38/a,http狀態碼666,匹配的是location ~* ^/[a-z]$,符合預期。

3.驗證第4條,其實第4條就至關因而總結性的匹配順序了:

nginx.conf配置:

#普通location
location /a {
     return 666;
}
 #普通location
location  /a/b {
     return 777;
}
#正則location 
location ~* /a/b { 
     return 888;
}

測試連接:http://192.168.88.38/a,http狀態碼666,匹配到普通location,location /a {return 666;},符合預期。
測試連接:http://192.168.88.38/a/b,http狀態碼777,先進行普通location匹配,遵循最大前綴原則,匹配到location /a/b {return 777; },可是,這只是一個臨時結果,由於接下來還要繼續往下進行正則location匹配,匹配到 location ~* /a/b { return 888; },最終返回結果爲888。符合預期。
將正則location的規則改下:

#普通location
location /a {
    return 666;
}
#普通location
location  /a/b {
    return 777;
}
#正則location
location ~* /a/c {
    return 888;
}

測試連接:http://192.168.88.38/a/b,http狀態碼777,匹配到location /a/b {return 777; },而且由於接下來沒有符合的正則location,因此最終返回爲777,符合預期。

綜上,location的匹配順序及結果取值都符合2,3,4點結論。
接下來再測試驗證普通location中的^~及=符號對於匹配搜索過程的阻斷效果,固然,別忘了這倆符號的真實做用。^~爲普通字符匹配,=爲精確匹配。
^~測試驗證nginx.conf配置:

location /a {
    return 666;
}
#普通匹配
location ^~ /a/b {
    return 777;
}
#正則location
location ~* /a/b {
    return 888;
}

測試連接:http://192.168.88.38/a/b,匹配到 location ^~ /a/b {return 777;}後,由於使用了^~符號,再也不繼續搜索正則location匹配,因此,雖然下面有符合條件的正則location,可是最終仍是返回了777,符合預期。
=測試驗證nginx.conf配置:

location /a {
    return 666;
}
#普通匹配
location = /a/b {
    return 777;
}
#正則location
location ~* /a/b {
    return 888;
}

測試連接:http://192.168.88.38/a/b,匹配到 location = /a/b {return 777;}後,由於使用了=符號,再也不繼續搜索正則location匹配,最終返回777,符合預期。

另附上經常使用正則表達式:

  • . : 匹配除換行符外的任意字符
  • ? : 重複0次或1次
  • : 重複1次或更屢次
  • : 重複0次或更屢次
  • d :匹配數字
  • ^ : 匹配字符串的開始
  • $ : 匹配字符串的結束
  • {n} : 重複n次
  • {n,} : 重複n次或更屢次
  • [c] : 匹配單個字符,如此處的字符 c
  • [a-z] : 匹配a-z小寫字母的任意一個
  • (a|b|c):匹配a或b或c</span>
相關文章
相關標籤/搜索