總結nginx中的location配置
前言
Location指令是nginx中最關鍵的指令之一,location指令的功能是用來匹配不同的url請求,進而對請求做不同的處理和響應,這其中較難理解的是多個location的匹配順序,本文會作為重點來解釋和說明。
開始之前先明確一些約定,我們輸入的網址叫做請求uri,nginx用請求uri與location中配置的uri做匹配。
nginx檔案結構
首先我們先簡單瞭解nginx的檔案結構,nginx的HTTP配置主要包括三個區塊,結構如下:
Global: nginx 執行相關
Events: 與使用者的網路連線相關
http
http Global: 代理,快取,日誌,以及第三方模組的配置
server
server Global: 虛擬主機相關
location: 地址定向,資料快取,應答控制,以及第三方模組的配置
從上面展示的nginx結構中可以看出location屬於請求級別配置,這也是我們最常用的配置。
所有的所有的所有的指令,都要以;結尾
配置 location 塊
location語法
Location 塊通過指定模式來與客戶端請求的URI相匹配。
Location基本語法:
匹配uri型別,有四種引數可選,當然也可以不帶引數。
命名location,用@來標識,類似於定義goto語句塊。
location [ = | ~ | ~* | ^~ ] /uri/ { … }
location @/name/ { … }
location匹配命令解釋
引數 | 解釋 |
---|---|
空 | location後沒有引數直接跟著URI,表示字首匹配,代表跟請求中的URI從頭開始匹配。 |
= | 用於標準 uri 前,要求請求字串與其嚴格匹配,成功則立即處理,nginx停止搜尋其他匹配。 |
^~ | 用於標準 uri 前,並要求一旦匹配到就會立即處理,不再去匹配其他的那些個正則 uri,一般用來匹配目錄 |
~ | 用於正則 uri 前,表示 uri 包含正則表示式, 區分大小寫 |
~* | # 用於正則 uri 前, 表示 uri 包含正則表示式, 不區分大小寫 |
@ | ”@“ 定義一個命名的 location,@定義的locaiton名字一般用在內部定向,例如error_page, try_files命令中。它的功能類似於程式設計中的goto。 |
location匹配順序
Nginx有兩層指令來匹配請求URI。第一個層次是server指令,它通過域名、ip和埠來做第一層級匹配,當找到匹配的server後就進入此server的location匹配。location的匹配並不完全按照它們在配置檔案中出現的順序來匹配,請求URI會按如下規則跟server裡配置的location匹配。
尋找有沒有“=”等號引數完全匹配的location,如果有完全匹配的等號location則停止匹配,執行該location中的指令,不去匹配其它型別的location。
匹配所有非正則表示式URI的location(包括空,=,^~ 三種引數)。找到請求URI和location URI按字首匹配最長的location,如果這個最長的location的引數是 ^~,則停止匹配,執行該location中的指令,否則暫存該location。
匹配正則表示式URI的location(包括~,~*兩種引數),按location在配置檔案中出現的順序匹配,如果找到第一個匹配的locaiton則停止匹配,執行該location。
匹配完所有正則表示式都沒有匹配的location,則執行第二步中暫存的最長字首匹配location。
資源搜尋網站大全 https://www.renrenfan.com.cn
簡單來說按這個規則 location 匹配命令的優先順序從高到低依次為(序號越小優先順序越高):
1. location = /a {…} #精準匹配
2. location ^~ /a {…} #字首匹配
3. location ~ /a.* {…} #正則匹配(區分大小寫)
4. location ~* /a.* {…} #正則匹配(不區分大小寫)
5. location /a {…} #最長字首匹配,但是優先順序低於正則匹配。 /a 和 ^~ /a 會衝突,報錯
6. location / {} #任何沒有匹配成功的,都會匹配這裡處理
讓我們用一個例子來說明上面的內容:
# 請求:
# /
# /index.html
# /documents/document.html
# /images/1.gif
# /documents/1.jpg
location = / {
# 只匹配 / 的查詢.
[ configuration A ]
}
# 能匹配成功: /
location / {
# 匹配任何請求,因為所有請求都是以”/"開始
# 但是更長字元匹配或者正則表示式匹配會優先匹配
[ configuration B ]
}
#能匹配成功:/index.html
location /documents/ {
# 匹配任何以 /documents/ 開頭的地址,匹配符合以後,還要繼續往下搜尋/
# 只有後面的正則表示式沒有匹配到時,這一條才會採用這一條/
[ configuration C ]
}
# 能匹配成功:/documents/document.html
location ~ /documents/ABC {
# 匹配任何以 /documents/ 開頭的地址,匹配符合以後,還要繼續往下搜尋/
# 只有後面的正則表示式沒有匹配到時,這一條才會採用這一條/
[ configuration CC ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 開頭的地址,匹配符合以後,停止往下搜尋正則,採用這一條。/
[ configuration D ]
}
# 能成功匹配:/images/1.gif
location ~* \.(gif|jpg|jpeg)$ {
# 匹配所有以 .gif、.jpg 或 .jpeg 結尾的請求,不區分大小寫
# 然而,所有請求 /images/ 下的圖片會被 [ config D ] 處理,因為 ^~ 到達不了這一條正則/
[ configuration E ]
}
# 能成功匹配:/documents/1.jpg
location /images/ {
# 字元匹配到 /images/,繼續往下,會發現 ^~ 存在/
[ configuration F ]
}
location /images/abc {
# 最長字元匹配到 /images/abc,繼續往下,會發現 ^~ 存在/
# F與G的放置順序是沒有關係的/
[ configuration G ]
}
location ~ /images/abc/ {
# 只有去掉 [ config D ] 才有效:先最長匹配 [ config G ] 開頭的地址,繼續往下搜尋,匹配到這一條正則,採用/
[ configuration H ]
}
location ~* /js/.*/\.js
匹配問號後的引數
請求URI中問號後面的引數是不能在location中匹配到的,這些引數儲存在$query_string變數中,可以用if來判斷。
例如,對於引數中帶有單引號’進行匹配然後重定向到錯誤頁面。
/plus/list.php?tid=19&mid=1124’
if ( $query_string ~* “.*[;’<>].*” ){
return 404;
}
location URI結尾帶不帶/
這個很多解釋不太準確,我有必要多說幾句。
對於請求URI結尾是否帶有/,一般的處理邏輯是帶/表示訪問目錄,不帶/表示訪問檔案,如果檔案不存在也會去匹配目錄。例如訪問http://www.nginx.cn/images/和...://www.nginx.cn/images,前面的請求會匹配目錄,後面的請求會先匹配檔案,檔案不存再匹配目錄
對於locatioin中的URI來說,如果URI的結尾帶有/,並且location要執行的命令式是proxy_pass、fastcgi_pass、uwsgi_pass、scgi_pass、memcached_pass、grpc_pass之一。例如:
location /images/ {
proxy_pass http://www.redis.com.cn
}
對於這種情況,nginx會做特殊處理,不管images命名的檔案或目錄存在不在,如果你訪問http://www.nginx.cn/images會...://www.nginx.cn/images/。
所以如果你想這兩種請求對應不同的處理,就要明確增加不帶/結尾的location配置。
location /images {
proxy_pass http://www.rabbitmq.cn
}
location /images/ {
proxy_pass http://www.redis.com.cn
}
命名location
帶有”@“的location是用來定義一個命名的location,這種location不參與請求匹配,一般用在內部定向。例如用在error_page, try_files命令中。它的功能類似於程式設計中的goto。
location /images {
try_files $uri $uri/ @name;
}
location @name {
…
}
實際使用建議
所以實際使用中,個人覺得至少有三個匹配規則定義,如下:
直接匹配網站根,通過域名訪問網站首頁比較頻繁,使用這個會加速處理,官網如是說。
這裡是直接轉發給後端應用伺服器了,也可以是一個靜態首頁。第一個必選規則:
location = / {
proxy_pass http://tomcat:8080/index
}
第二個必選規則是處理靜態檔案請求,這是nginx作為http伺服器的強項,有兩種配置模式,目錄匹配或字尾匹配,任選其一或搭配使用:
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
第三個規則就是通用規則,用來轉發動態請求到後端應用伺服器,非靜態檔案請求就預設是動態請求,自己根據實際把握,畢竟目前的一些框架的流行,帶.php,.jsp字尾的情況很少了:
location / {
proxy_pass http://tomcat:8080/
}