目錄:
一、常用的Nginx 正則表達式
二、location
三、rewrite
一、常用的Nginx 正則表達式
1 ^ :匹配輸入字符串的起始位置 2 $ :匹配輸入字符串的結束位置 3 * :匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll” 4 + :匹配前面的字符一次或多次。如“ol+”能匹配“ol”及“oll”、“olll”,但不能匹配“o” 5 ? :匹配前面的字符零次或一次,例如“do(es)?”能匹配“do”或者“does”,”?”等效於”{0,1}” 6 . :匹配除“\n”之外的任何單個字符,若要匹配包括“\n”在內的任意字符,請使用諸如“[.\n]”之類的模式 7 \ :將后面接着的字符標記為一個特殊字符或一個原義字符或一個向后引用。如“\n”匹配一個換行符,而“\$”則匹配“$” 8 \d :匹配純數字 9 {n} :重復 n 次 10 {n,} :重復 n 次或更多次 11 {n,m} :重復 n 到 m 次 12 [] :定義匹配的字符范圍 13 [c] :匹配單個字符 c 14 [a-z] :匹配 a-z 小寫字母的任意一個 15 [a-zA-Z0-9] :匹配所有大小寫字母或數字 16 () :表達式的開始和結束位置 17 | :或運算符
從功能看 rewrite 和 location 似乎有點像,都能實現跳轉,主要區別在於 rewrite 是在同一域名內更改獲取資源的路徑,而 location 是對一類路徑做控制訪問或反向代理,還可以proxy_pass 到其他機器
二、location
location 大致可以分為三類
精准匹配:location = / {} 一般匹配:location / {} 正則匹配:location ~ / {}
location 常用的匹配規則
1 = :進行普通字符精確匹配,也就是完全匹配。 2 ^~ :表示普通字符匹配。使用前綴匹配。如果匹配成功,則不再匹配其它 location。 3 ~ :區分大小寫的匹配。 4 ~* :不區分大小寫的匹配。 5 !~ :區分大小寫的匹配取非。 6 !~* :不區分大小寫的匹配取非。
location 優先級
首先精確匹配 = 其次前綴匹配 ^~ 其次是按文件中順序的正則匹配 ~或~* 然后匹配不帶任何修飾的前綴匹配 最后是交給 / 通用匹配
location 示例說明
1 (1)location = / {} 2 =為精確匹配 / ,主機名后面不能帶任何字符串,比如訪問 / 和 /data,則 / 匹配,/data 不匹配 3 再比如 location = /abc,則只匹配/abc ,/abc/或 /abcd不匹配。若 location /abc,則即匹配/abc 、/abcd/ 同時也匹配 /abc/。 4 5 (2)location / {} 6 因為所有的地址都以 / 開頭,所以這條規則將匹配到所有請求 比如訪問 / 和 /data, 則 / 匹配, /data 也匹配, 7 但若后面是正則表達式會和最長字符串優先匹配(最長匹配) 8 9 (3)location /documents/ {} 10 匹配任何以 /documents/ 開頭的地址,匹配符合以后,還要繼續往下搜索其它 location 11 只有其它 location后面的正則表達式沒有匹配到時,才會采用這一條 12 13 (4)location /documents/abc {} 14 匹配任何以 /documents/abc 開頭的地址,匹配符合以后,還要繼續往下搜索其它 location 15 只有其它 location后面的正則表達式沒有匹配到時,才會采用這一條 16 17 (5)location ^~ /images/ {} 18 匹配任何以 /images/ 開頭的地址,匹配符合以后,停止往下搜索正則,采用這一條 19 20 (6)location ~* \.(gif|jpg|jpeg)$ {} 21 匹配所有以 gif、jpg或jpeg 結尾的請求 22 然而,所有請求 /images/ 下的圖片會被 location ^~ /images/ 處理,因為 ^~ 的優先級更高,所以到達不了這一條正則 23 24 (7)location /images/abc {} 25 最長字符匹配到 /images/abc,優先級最低,繼續往下搜索其它 location,會發現 ^~ 和 ~ 存在 26 27 (8)location ~ /images/abc {} 28 匹配以/images/abc 開頭的,優先級次之,只有去掉 location ^~ /images/ 才會采用這一條 29 30 (9)location /images/abc/1.html {} 31 匹配/images/abc/1.html 文件,如果和正則 ~ /images/abc/1.html 相比,正則優先級更高
優先級總結
(location =) > (location 完整路徑) > (location ^~ 路徑) > (location ~,~* 正則順序) > (location 部分起始路徑) > (location /)
實際網站使用中,至少有三個匹配規則定義
1 #第一個必選規則 2 直接匹配網站根,通過域名訪問網站首頁比較頻繁,使用這個會加速處理,比如說官網。 3 這里是直接轉發給后端應用服務器了,也可以是一個靜態首頁 4 location = / { 5 proxy_pass http://tomcat_server/; 6 } 7 8 #第二個必選規則是處理靜態文件請求,這是nginx作為http服務器的強項 9 有兩種配置模式,目錄匹配或后綴匹配,任選其一或搭配使用 10 location ^~ /static/ { 11 root /webroot/static/; 12 } 13 14 location ~* \.(html|gif|jpg|jpeg|png|css|js|ico)$ { 15 root /webroot/res/; 16 } 17 18 #第三個規則就是通用規則,比如用來轉發帶.php、.jsp后綴的動態請求到后端應用服務器 19 非靜態文件請求就默認是動態請求 20 location / { 21 proxy_pass http://tomcat_server; 22 }
三、rewrite
- rewrite功能就是,使用nginx提供的全局變量或自己設置的變量,結合正則表達式和標志位實現url重寫以及重定向
- rewrite只能放在server{},location{},if{}中,並且默認只能對域名后邊的除去傳遞的參數外的字符串起作用
例如 http://www.kgc.com/test/HTML/index.php?id=1&u=str 只對/test/HTML/index.php重寫
rewrite 執行順序如下
(1) 執行 server 塊里面的 rewrite 指令。 (2) 執行 location 匹配。 (3) 執行選定的 location 中的 rewrite 指令。
語法rewrite <regex> <replacement> [flag]
1 regex :表示正則匹配規則。 2 replacement :表示跳轉后的內容。 3 flag :表示 rewrite 支持的 flag 標記。 4 5 6 ###flag標記說明### 7 last :本條規則匹配完成后,繼續向下匹配新的location URI規則,一般用在 server 和 if 中。 8 break :本條規則匹配完成即終止,不再匹配后面的任何規則,一般使用在 location 中。 9 redirect :返回302臨時重定向,瀏覽器地址會顯示跳轉后的URL地址。 10 permanent :返回301永久重定向,瀏覽器地址欄會顯示跳轉后的URL地址。
rewrite 基於域名的跳轉
1 現在公司舊域名www.kgc.com有業務需求變更,需要使用新域名www.benet.com代替,但是舊域名不能廢除,需要跳轉到新域名上,而且后面的參數保持不變。 2 vim /usr/local/nginx/conf/nginx.conf 3 server { 4 listen 80; 5 server_name www.kgc.com; #域名修改 6 charset utf-8; 7 access_log /var/log/nginx/www.kgc.com-access.log; #日志修改 8 location / { 9 #添加域名重定向 10 if ($host = 'www.kgc.com'){ #$host為rewrite全局變量,代表請求主機頭字段或主機名 11 rewrite ^/(.*)$ http://www.benet.com/$1 permanent; #$1為正則匹配的內容,即域名后邊的字符串 12 } 13 root html; 14 index index.html index.htm; 15 } 16 } 17 18 19 echo "192.168.80.10 www.kgc.com www.benet.com" >> /etc/hosts 20 systemctl restart nginx 21 瀏覽器輸入模擬訪問 http://www.kgc.com/test/1.html(雖然這個請求內容是不存在的) 22 會跳轉到www.benet.com/test/1.html,查看元素可以看到返回301,實現了永久重定向跳轉,而且域名后的參數也正常跳轉。
基於客戶端 IP 訪問跳轉
1 今天公司業務新版本上線,要求所有 IP 訪問任何內容都顯示一個固定維護頁面,只有公司 IP :192.168.116.60訪問正常。 2 vim /usr/local/nginx/conf/nginx.conf 3 server { 4 listen 80; 5 server_name www.kgc.com; #域名修改 6 charset utf-8; 7 access_log /var/log/nginx/www.kgc.com-access.log; #日志修改 8 9 #設置是否合法的IP標記 10 set $rewrite true; #設置變量$rewrite,變量值為boole值true 11 #判斷是否為合法IP 12 if ($remote_addr = "192.168.116.60"){ #當客戶端IP為192.168.80.10時,將變量值設為false,不進行重寫 13 set $rewrite false; 14 } 15 #除了合法IP,其它都是非法IP,進行重寫跳轉維護頁面 16 if ($rewrite = true){ #當變量值為true時,進行重寫 17 rewrite (.+) /weihu.html; #重寫在訪問IP后邊插入/weihu.html,例如192.168.116.60/weihu.html 18 } 19 location = /weihu.html { 20 root /var/www/html; #網頁返回/var/www/html/weihu.html的內容 21 } 22 23 location / { 24 root html; 25 index index.html index.htm; 26 } 27 } 28 29 30 mkdir -p /var/www/html/ 31 echo "<h1>We are maintaining now!</h1>" > /var/www/html/weihu.html 32 systemctl restart nginx 33 只有 IP 為 192.168.116.60 能正常訪問,其它地址都是維護頁面
如果rewrite (.+) /weihu.html;改成rewrite (.+) /weihu.html permanent; 的話,如果是非192.168.80.10的主機訪問會使瀏覽器修改請求訪問的URL成http://www.kgc.com/weihu.html再請求訪問, 這樣就會進入一直在rewrite的死循環,訪問請求會一直被重寫成http://www.kgc.com/weihu.html再請求訪問
基於舊域名跳轉到新域名后面加目錄
1 現在訪問的是 http://bbs.kgc.com/post/,現在需要將這個域名下面的訪問都跳轉到http://www.kgc.com/bbs/post 2 vim /usr/local/nginx/conf/nginx.conf 3 server { 4 listen 80; 5 server_name bbs.kgc.com; #域名修改 6 charset utf-8; 7 access_log /var/log/nginx/www.kgc.com-access.log; 8 #添加 9 location /post { 10 rewrite (.+) http://www.kgc.com/bbs$1 permanent; #這里的$1為位置變量,代表/post 11 } 12 13 location / { 14 root html; 15 index index.html index.htm; 16 } 17 } 18 19 20 mkdir -p /usr/local/nginx/html/bbs/post 21 echo "this is 1.html" >> /usr/local/nginx/html/bbs/post/2.html 22 echo "192.168.80.11 bbs.kgc.com" >> /etc/hosts 23 systemctl restart nginx 24 使用瀏覽器訪問 http://bbs.kgc.com/ post/1.html 跳轉到 http://www.kgc.com/bbs/post/1.html
基於參數匹配的跳轉
1 現在訪問http://www.kgc.com/100-(100|200)-100.html 跳轉到http://www.kgc.com頁面。 2 vim /usr/local/nginx/conf/nginx.conf 3 server { 4 listen 80; 5 server_name www.kgc.com; #域名修改 6 charset utf-8; 7 access_log /var/log/nginx/www.kgc.com-access.log main; 8 9 if ($request_uri ~ ^/100-(100|200)-(\d+).html$) { 10 rewrite (.*) http://www.kgc.com permanent; 11 } 12 13 location / { 14 root html; 15 index index.html index.htm; 16 } 17 } 18 19 systemctl restart nginx 20 使用瀏覽器訪問 http://www.kgc.com/100-200-100.html 或 http://www.kgc.com/100-100-100.html 跳轉到http://www.kgc.com頁面。
$request_uri: 包含請求參數的原始URI,不包含主機名,如: http://www.kgc.com/abc/bbs/index.html?a=1&b=2中的/abc/bbs/index.php?a=1&b=2 $uri:這個變量指當前的請求URI,不包括任何參數,如: /abc/bbs/index.html $document_uri: 與$uri相同, 這個變量指當前的請求URI,不包括任何傳遞參數,如:/abc/bbs/index.html
基於目錄下所有 php 結尾的文件跳轉
1 要求訪問 http://www.kgc.com/upload/123.php 跳轉到首頁。 2 vim /usr/local/nginx/conf/nginx.conf 3 server { 4 listen 80; 5 server_name www.kgc.com; #域名修改 6 charset utf-8; 7 access_log /var/log/nginx/www.kgc.com-access.log main; 8 9 location ~* /upload/.*\.php$ { 10 rewrite (.+) http://www.kgc.com permanent; 11 } 12 13 location / { 14 root html; 15 index index.html index.htm; 16 } 17 } 18 19 systemctl restart nginx 20 瀏覽器訪問 http://www.kgc.com/upload/123.php 跳轉到http://www.kgc.com頁面。
基於最普通一條 url 請求的跳轉
1 要求訪問一個具體的頁面如 http://www.kgc.com/abc/123.html 跳轉到首頁 2 vim /usr/local/nginx/conf/nginx.conf 3 server { 4 listen 80; 5 server_name www.kgc.com; #域名修改 6 charset utf-8; 7 access_log /var/log/nginx/www.kgc.com-access.log main; 8 9 location ~* ^/abc/123.html { 10 rewrite (.+) http://www.kgc.com permanent; 11 } 12 13 location / { 14 root html; 15 index index.html index.htm; 16 } 17 } 18 19 systemctl restart nginx 20 瀏覽器訪問 http://www.kgc.com/abc/123.html 跳轉到http://www.kgc.com頁面。