Nginx之Location匹配規則


概述

經過多年發展,nginx憑借其優異的性能征服了互聯網界,成為了各個互聯網公司架構設計中不可獲取的要素。Nginx是一門大學問,但是對於Web開發者來說,最重要的是需要能捋的清楚Nginx的請求路由配置。

Nginx的路由配置放在配置文件中的Location子節,下面我們來熟練掌握Location的配置。

語法規則

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

location 為關鍵字 類似java中的case關鍵字,關鍵字后跟隨可選的修飾符,然后是匹配規則(正則匹配和模式匹配),后面的代碼塊為請求處理或轉發的邏輯。

修飾符

一共4種修飾符:

  1. = 表示精確匹配。只有請求的url路徑與后面的字符串完全相等時,才會命中。
  2. ~ 表示該規則是使用正則定義的,區分大小寫。
  3. ~* 表示該規則是使用正則定義的,不區分大小寫。
  4. ^~ 表示前綴匹配,在正則之前。如果該符號后面的字符是最佳匹配,采用該規則,不再進行后續的查找。
  5. 空修飾符,表示前綴匹配,但是在正則匹配之后。

「=」 修飾符-完全匹配

特點:要求路徑完全匹配

 server {
     server_name website.com;
     location = /abcd {
     	[…]
     }
 }
  • http://website.com/abcd匹配
  • http://website.com/ABCD可能會匹配 ,也可以不匹配,取決於操作系統的文件系統是否大小寫敏感
  • http://website.com/abcd?param1&param2匹配,忽略 querystring
  • http://website.com/abcde**不匹配

「~」修飾符-正則匹配

特點:區分大小寫的正則匹配

server {
server_name website.com;
	location ~ ^/abcd$ {
		[…]
	}
}

注意: ^/abcd$這個正則表達式表示字符串必須以/開始,以$結束,中間必須是abcd

  • http://website.com/abcd匹配(完全匹配)
  • http://website.com/ABCD不匹配,大小寫敏感
  • http://website.com/abcd?param1&param2匹配
  • http://website.com/abcd/不匹配,不能匹配正則表達式
  • http://website.com/abcde不匹配,不能匹配正則表達式

「~*」修飾符-正則匹配

特點:不區分大小寫的正則匹配

 server {
     server_name website.com;
     location ~* ^/abcd$ {
     	[…]
     }
 }
  • http://website.com/abcd匹配 (完全匹配)
  • http://website.com/ABCD匹配 (大小寫不敏感)
  • http://website.com/abcd?param1&param2匹配
  • http://website.com/abcd/ 不匹配,不能匹配正則表達式
  • http://website.com/abcde 不匹配,不能匹配正則表達式

「^~」修飾符-模式匹配

前綴匹配 如果該 location 是最佳的匹配,那么對於匹配這個 location 的字符串, 該修飾符不再進行正則表達式檢測。注意,這不是一個正則表達式匹配,它的目的是優先於正則表達式的匹配

匹配過程

對請求的url序列化。例如,對%xx等字符進行解碼,去除url中多個相連的/,解析url中的...等。這一步是匹配的前置工作。

location有兩種表示形式,一種是使用前綴字符,一種是使用正則。如果是正則的話,前面有~~*修飾符。

具體的匹配過程如下:

首先先檢查使用前綴字符定義的location,選擇最長匹配的項並記錄下來。

如果找到了精確匹配的location,也就是使用了=修飾符的location,結束查找,使用它的配置。

然后按順序查找使用正則定義的location,如果匹配則停止查找,使用它定義的配置。

如果沒有匹配的正則location,則使用前面記錄的最長匹配前綴字符location。

基於以上的匹配過程,我們可以得到以下兩點啟示:

  1. 使用正則定義的location在配置文件中出現的順序很重要。因為找到第一個匹配的正則后,查找就停止了,后面定義的正則就是再匹配也沒有機會了。
  2. 使用精確匹配可以提高查找的速度。例如經常請求/的話,可以使用=來定義location。

匹配規則

原則: 先精確匹配,沒有則查找帶有 ^~的前綴匹配,沒有則進行正則匹配,最后才返回前綴匹配的結果(如果有的話)

  1. 首先精確匹配 =
  2. 其次前綴匹配 ^~
  3. 其次是按文件中順序的正則匹配
  4. 然后匹配不帶任何修飾的前綴匹配。
  5. 最后是交給 / 通用匹配
  6. 當有匹配成功時候,停止匹配,按當前匹配規則處理請求

注意:前綴匹配,如果有包含關系時,按最大匹配原則進行匹配。比如在前綴匹配:location /dir01location /dir01/dir02,如有請求 http://localhost/dir01/dir02/file 將最終匹配到 location /dir01/dir02

匹配邏輯偽代碼:

 function match(uri):
  rv = NULL
  
  if uri in exact_match:
    return exact_match[uri]
  
  if uri in prefix_match:
    if prefix_match[uri] is '^~':
      return prefix_match[uri]
    else:
      rv = prefix_match[uri] // 注意這里沒有 return,且這里是最長匹配
   
  if uri in regex_match:
    return regex_match[uri] // 按文件中順序,找到即返回
  return rv```

URL尾部的/

關於URL尾部的/有三點也需要說明一下。第一點與location配置有關,其他兩點無關。

  1. location中的字符有沒有/都沒有影響。也就是說/user//user是一樣的。
  2. 如果URL結構是https://domain.com/的形式,尾部有沒有/都不會造成重定向。因為瀏覽器在發起請求的時候,默認加上了/。雖然很多瀏覽器在地址欄里也不會顯示/。這一點,可以訪問baidu驗證一下。
  3. 如果URL的結構是https://domain.com/some-dir/。尾部如果缺少/將導致重定向。因為根據約定,URL尾部的/表示目錄,沒有/表示文件。所以訪問/some-dir/時,服務器會自動去該目錄下找對應的默認文件。如果訪問/some-dir的話,服務器會先去找some-dir文件,找不到的話會將some-dir當成目錄,重定向到/some-dir/,去該目錄下找默認文件。可以去測試一下你的網站是不是這樣的。

總結

location的配置有兩種形式,前綴字符和正則。查找匹配的時候,先查找前綴字符,選擇最長匹配項,再查找正則。正則的優先級高於前綴字符。

正則的查找是按照在配置文件中的順序進行的。因此正則的順序很重要,建議越精細的放的越靠前。

使用=精准匹配可以加快查找的順序,如果根域名經常被訪問的話建議使用=

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM