一份簡單夠用的 Nginx Location 配置講解

前言

Location 是 Nginx 中一個非常核心的配置,這篇重點講解一下 Location 的配置問題以及一些注意事項。

語法

關於 Location,舉個簡單的配置例子:

http { 
  server {
      listen 80;
    	server_name www.yayujs.com;
    	location / {
      	root /home/www/ts/;
	      index index.html;
    	}
  }
}

大致的意思是,當你訪問 www.yayujs.com80 端口的時候,返回 /home/www/ts/index.html 文件。

我們看下 Location 的具體語法:

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

重點看方括號中的 [ = | ~ | ~* | ^~ ],其中 | 分隔的內容表示你可能會用到的語法,其中:

location = /test {
  return 200 "hello";
}

# /test ok
# /test/ not ok
# /test2 not ok
# /test/2 not ok
location ~ ^/test$ {
  [ configuration ] 
}

# /test ok
# /Test not ok
# /test/ not ok
# /test2 not ok
location ~* ^/test$ {     
	[ configuration ] 
}

# /test ok
# /Test ok
# /test/ not ok
# /test2 not ok
location ^~ /images/ {    
	[ configuration ] 
}

# /images/1.gif ok

而當你不使用這些語法的時候,只寫 uri 的時候:

/ 表示通用匹配:

location / {     
	[ configuration ] 
}

# /index.html ok
location /test {
    [ configuration ] 
}

# /test ok
# /test2 ok
# /test/ ok

匹配順序

當存在多個 location 的時候,他們的匹配順序引用 Nginx 官方文檔就是:

A location can either be defined by a prefix string, or by a regular expression. Regular expressions are specified with the preceding “~*” modifier (for case-insensitive matching), or the “~” modifier (for case-sensitive matching). To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered. Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used.

If the longest matching prefix location has the “^~” modifier then regular expressions are not checked.

Also, using the “=” modifier it is possible to define an exact match of URI and location. If an exact match is found, the search terminates. For example, if a “/” request happens frequently, defining “location = /” will speed up the processing of these requests, as search terminates right after the first comparison. Such a location cannot obviously contain nested locations.

翻譯整理後就是:

location 的定義分爲兩種:

而匹配 location 的順序爲:

  1. 檢查使用前綴字符串的 locations,在使用前綴字符串的 locations 中選擇最長匹配的,並將結果進行儲存

  2. 如果符合帶有 = 修飾符的 URI,則立刻停止匹配

  3. 如果符合帶有  ^~ 修飾符的 URI,則也立刻停止匹配。

  4. 然後按照定義文件的順序,檢查正則表達式,匹配到就停止

  5. 當正則表達式匹配不到的時候,使用之前儲存的前綴字符串

再總結一下就是:

在順序上,前綴字符串順序不重要,按照匹配長度來確定,正則表達式則按照定義順序。

在優先級上,= 修飾符最高,^~ 次之,再者是正則,最後是前綴字符串匹配。

我們舉幾個簡單的例子複習下:

server {
    location /doc {
        [ configuration A ] 
    }
    location /docu {
        [ configuration B ] 
    }
}

# 請求 /document 使用 configuration B
# 雖然 /doc 也能匹配到,但在順序上,前綴字符串順序不重要,按照匹配長度來確定
server {
    location ~ ^/doc {
        [ configuration A ] 
    }
    location ~ ^/docu {
        [ configuration B ] 
    }
}

# 請求 /document 使用 configuration A
# 雖然 ~ ^/docu 也能匹配到,但正則表達式則按照定義順序
server {
    location ^~ /doc {
        [ configuration A ] 
    }
    location ~ ^/docu {
        [ configuration B ] 
    }
}

# 請求 /document 使用 configuration A
# 雖然 ~ ^/docu 也能匹配到,但 ^~ 的優先級更高
server {
    location /document {
        [ configuration A ] 
    }
    location ~ ^/docu {
        [ configuration B ] 
    }
}

# 請求 /document 使用 configuration B
# 雖然 /document 也能匹配到,但正則的優先級更高

root 與 alias 的區別

當我們這樣設置 root 的時候:

location /i/ {
    root /data/w3;
}

當請求 /i/top.gif/data/w3/i/top.gif 會被返回。

當我們這樣設置 alias 的時候:

location /i/ {
    alias /data/w3/images/;
}

當請求 /i/top.gif/data/w3/images/top.gif 會被返回。

乍一看兩者很像,但細一看,就能看出兩者的區別,root 是直接拼接 root + location 而 alias 是用 alias 替換 location,所以 root 中最後的路徑裏有 /i/,而 alias 中最後的路徑裏沒有  /i/

所以如果你這樣使用 allias 定義一個路徑:

location /images/ {
    alias /data/w3/images/;
}

其實使用 root 會更好:

location /images/ {
    root /data/w3;
}

server 和 location 中的 root

server 和 location 中都可以使用 root,舉個例子:

http { 
  server {
      listen 80;
    	server_name www.yayujs.com;
    	root /home/www/website/;
    	location / {
      	root /home/www/ts/;
	      index index.html;
    	}
  }
}

如果兩者都出現,是怎樣的優先級呢?

簡單的來說,就是就近原則,如果 location 中能匹配到,就是用 location 中的 root 配置,忽略 server 中的 root,當 location 中匹配不到的時候,則使用 server 中的 root 配置。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/mIbcSTAbokDGhdl77efYdw