Nginx中的 location 匹配和 rewrite 重寫跳轉
Nginx中的location匹配和rewrite重寫跳轉
1、常用的Nginx正則表示式
2、location
3、rewrite
4、rewrite例項
1、常用的Nginx正則表示式:
^ :匹配輸入字串的起始位置 $ :匹配輸入字串的結束位置 * :匹配前面的字元零次或多次。如“ol*”能匹配“o”及“ol”、“oll” + :匹配前面的字元一次或多次。如“ol+”能匹配“ol”及“oll”、“olll”,但不能匹配“o” ? :匹配前面的字元零次或一次,例如“do(es)?”能匹配“do”或者“does”,”?”等效於”{0,1}” . :匹配除“\n”之外的任何單個字元,若要匹配包括“\n”在內的任意字元,請使用諸如“[.\n]”之類的模式 \ :將後面接著的字元標記為一個特殊字元或一個原義字元或一個向後引用。如“\n”匹配一個換行符,而“\$”則匹配“$” \d :匹配純數字 {n} :重複 n 次 {n,} :重複 n 次或更多次 {n,m} :重複 n 到 m 次 [] :定義匹配的字元範圍 [c] :匹配單個字元 c [a-z] :匹配 a-z 小寫字母的任意一個 [a-zA-Z0-9] :匹配所有大小寫字母或數字 () :表示式的開始和結束位置 | :或運算子
2、location:
location大致可以分為是三類:
- 精準匹配:location = / {}
- 一般匹配:location / {}
- 正則匹配:location ~ / {}
location常用匹配規則:
= :進行普通字元精確匹配,也就是完全匹配。 ^~ :表示普通字元匹配。使用字首匹配。如果匹配成功,則不再匹配其它 location。 ~ :區分大小寫的匹配。 ~* :不區分大小寫的匹配。 !~ :區分大小寫的匹配取非。 !~* :不區分大小寫的匹配取非。
location優先順序: 重點
首先精確匹配 = 其次字首匹配 ^~ 其次是按檔案中順序的正則匹配 ~或~* 然後匹配不帶任何修飾的字首匹配 最後是交給 / 通用匹配
location示例說明:
(1)location = / {} =為精確匹配 / ,主機名後面不能帶任何字串,比如訪問 / 和 /data,則 / 匹配,/data 不匹配 再比如 location = /abc,則只匹配/abc ,/abc/或 /abcd不匹配。若 location /abc,則即匹配/abc 、/abcd/ 同時也匹配 /abc/。 (2)location / {} 因為所有的地址都以 / 開頭,所以這條規則將匹配到所有請求 比如訪問 / 和 /data, 則 / 匹配, /data 也匹配, 但若後面是正則表示式會和最長字串優先匹配(最長匹配) (3)location /documents/ {} 匹配任何以 /documents/ 開頭的地址,匹配符合以後,還要繼續往下搜尋其它 location 只有其它 location後面的正則表示式沒有匹配到時,才會採用這一條 (4)location /documents/abc {} 匹配任何以 /documents/abc 開頭的地址,匹配符合以後,還要繼續往下搜尋其它 location 只有其它 location後面的正則表示式沒有匹配到時,才會採用這一條 (5)location ^~ /images/ {} 匹配任何以 /images/ 開頭的地址,匹配符合以後,停止往下搜尋正則,採用這一條 (6)location ~* \.(gif|jpg|jpeg)$ {} 匹配所有以 gif、jpg或jpeg 結尾的請求 然而,所有請求 /images/ 下的圖片會被 location ^~ /images/ 處理,因為 ^~ 的優先順序更高,所以到達不了這一條正則 (7)location /images/abc {} 最長字元匹配到 /images/abc,優先順序最低,繼續往下搜尋其它 location,會發現 ^~ 和 ~ 存在 (8)location ~ /images/abc {} 匹配以/images/abc 開頭的,優先順序次之,只有去掉 location ^~ /images/ 才會採用這一條 (9)location /images/abc/1.html {} 匹配/images/abc/1.html 檔案,如果和正則 ~ /images/abc/1.html 相比,正則優先順序更高 優先順序總結: (location =) > (location 完整路徑) > (location ^~ 路徑) > (location ~,~* 正則順序) > (location 部分起始路徑) > (location /)
實際網站使用中,至少有三個匹配規則定義 :
第一個必選規則 直接匹配網站根,通過域名訪問網站首頁比較頻繁,使用這個會加速處理,比如說官網。 這裡是直接轉發給後端應用伺服器了,也可以是一個靜態首頁
location = / { proxy_pass http://tomcat_server/; }
第二個必選規則 處理靜態檔案請求,這是nginx作為http伺服器的強項 有兩種配置模式,目錄匹配或字尾匹配, 任選其一或搭配使用
location ^~ /static/ { root /webroot/static/; } location ~* \.(html|gif|jpg|jpeg|png|css|js|ico)$ { root /webroot/res/; }
第三個規則 通用規則 比如用來轉發帶.php、.jsp字尾的動態請求到後端應用伺服器 非靜態檔案請求就預設是動態請求
location / { proxy_pass http://tomcat_server; }
3、rewrite:
rewrite功能就是使用nginx提供的全域性變數或自己設定的變數,結合正則表示式和標記實現URL重寫以及重定向。
例如:更換域名後需要保持舊的域名能夠轉到新的域名上、某網頁發生改變需要跳轉到新的頁面、網站防盜鏈等等需求。
rewrite只能放在server{},location{},if{}中,並且預設只能對域名後面的除去傳遞的引數外的字串起作用。
例如:http://www.lvbu.com/a/we/index.php?id=1&u=str 只對/a/we/index.php重寫。
a)rewrite 跳轉實現
Nginx:通過ngx_http_rewrite_module模組支援URL重寫、支援if條件判斷,但不支援else
跳轉:從一個location跳轉到另一個location,迴圈最多可以執行10次,超過後nginx將返回500錯誤
PCRE支援:perl相容正則表示式的語法規則匹配
重寫模組set指令:建立新的變數併為其賦值
b)rewrite執行順序
- 執行server塊裡面的rewrite指令
- 執行location匹配
- 執行選定的location中的rewrite指令
c)rewrite語法格式
- 語法rewrite<regex><replacement><flag>;
- regex:表示正則匹配規則
- replacement:表示跳轉後的內容
- flag:表示rewrite支援的flag標記
d)flag標記說明
- last :本條規則匹配完成後,繼續向下匹配新的location URI規則,一般用在 server 和 if 中。
- break :本條規則匹配完成即終止,不再匹配後面的任何規則,一般使用在 location 中。
- redirect :返回302臨時重定向,瀏覽器地址會顯示跳轉後的URL地址。
- permanent :返回301永久重定向,瀏覽器位址列會顯示跳轉後的URL地址。
4、rewrite例項:
a)基於域名的跳轉:
現在公司舊域名www.lvbu.com有業務需求變更,需要使用新域名www.caocao.com代替,
但是舊域名不能廢除,需要跳轉到新域名上,而且後面的引數保持不變。
vim /usr/local/nginx/conf/nginx.conf server { listen 80; server_name www.lvbu.com; #域名修改 charset utf-8; access_log /var/log/nginx/www.lvbu.com.access.log; #日誌修改 location / { #新增域名重定向 if ($host = 'www.lvbu.com'){ #$host為rewrite全域性變數,代表請求主機頭欄位或主機名 rewrite ^/(.*)$ http://www.caocao.com/$1 permanent; #$1為正則匹配的內容,即域名後邊的字串 } root html; index index.html index.htm; } }
b)基於客戶端ip訪問跳轉:
今天公司業務新版本上線,要求所有 IP 訪問任何內容都顯示一個固定維護頁面,只有公司 IP :20.0.0.17訪問正常。
vim /usr/local/nginx/conf/nginx.conf server { listen 80; server_name www.lvbu.com; #域名修改 charset utf-8; access_log /var/log/nginx/www.lvbu.com-access.log main; #日誌修改 #設定是否合法的IP標記 set $rewrite true; #設定變數$rewrite,變數值為boole值true #判斷是否為合法IP if ($remote_addr = "20.0.0.17"){ #當客戶端IP為20.0.0.17時,將變數值設為false,不進行重寫 set $rewrite false; } #除了合法IP,其它都是非法IP,進行重寫跳轉維護頁面 if ($rewrite = true){ #當變數值為true時,進行重寫 rewrite (.+) /weihu.html; #重寫在訪問IP後邊插入/weihu.html,例如20.0.0.18/weihu.html } location = /weihu.html { root /var/www/html; #網頁返回/var/www/html/weihu.html的內容 } location / { root html; index index.html index.htm; } }
mkdir -p /var/www/html/ echo 'hello weihu!' > /var/www/html/weihu.html systemctl restart nginx
c)基於舊域名跳轉到新域名後面加目錄:
現在訪問的是 http://caocao.lvbu.com,現在需要將這個域名下面的訪問都跳轉到http://www.lvbu.com/caocao
vim /usr/local/nginx/conf/nginx.conf server { listen 80; server_name caocao.lvbu.com; #域名修改 charset utf-8; access_log /var/log/nginx/www.lvbu.com-access.log; #新增 location /post { rewrite (.+) http://www.lvbu.com/caocao$1 permanent; #這裡的$1為位置變數,代表/post } location / { root html; index index.html index.htm; } }
mkdir -p /usr/local/nginx/html/kiki/post systemctl restart nginx.service
d) 基於引數匹配的跳轉:
現在訪問http://www.lvbu.com/100-(100|200)-100.html 跳轉到http://www.lvbu.com頁面。vim /usr/local/nginx/conf/nginx.conf server { listen 80; server_name www.lvbu.com; #域名修改 charset utf-8; access_log /var/log/nginx/www.lvbu.com-access.log main; if ($request_uri ~ ^/100-(100|200)-(\d+).html$) { rewrite (.+) http://www.lvbu.com permanent; } location / { root html; index index.html index.htm; } }
systemctl restart nginx
e)基於目錄下所有 php 結尾的檔案跳轉 :
要求訪問 http://www.lvbu.com/upload/123.php 跳轉到首頁。vim /usr/local/nginx/conf/nginx.conf server { listen 80; server_name www.lvbu.com; #域名修改 charset utf-8; access_log /var/log/nginx/www.lvbu.com-access.log main; location ~* /upload/.*\.php$ { rewrite (.+) http://www.lvbu.com permanent; } location / { root html; index index.html index.htm; } }
systemctl restart nginx
f)基於最普通一條 url 請求的跳轉:
要求訪問一個具體的頁面如 http://www.lvbu.com/abc/123.html 跳轉到首頁vim /usr/local/nginx/conf/nginx.conf server { listen 80; server_name www.lvbu.com; #域名修改 charset utf-8; access_log /var/log/nginx/www.lvbu.com-access.log main; location ~* ^/abc/123.html { rewrite (.+) http://www.lvbu.com permanent; } location / { root html; index index.html index.htm; } }
systemctl restart nginx
自古英雄多磨難