Rewrite主要的功能是實現URL重寫,Nginx 的 Rewrite 規則采用 PCRE Perl 兼容正則表達式的語法進行規則匹配,如相使用 Nginx 的 Rewrite 功能,在編譯 Nginx 前要編譯安裝 PCRE 庫。Rewrite主要實現url地址重寫,以及重定向,就是把傳入web的請求重定向到其他url的過程。
rewrite和location的功能有點相像,都能實現跳轉,主要區別在于rewrite常用于同一域名內更改獲取資源的路徑,而location是對一類路徑做控制訪問和反向代理,可以proxy_pass到其他服務器。
Nginx提供的全局變量或自己設置的變量,結合正則表達式和標志位實現url重寫以及重定向。
rewrite只能放在server{},location{},if{}中,
并且只能對域名后邊的除去傳遞的參數外的字符串起作用。
Rewrite主要的功能就是實現URL的重寫,Nginx的Rewrite規則采用Pcre,perl兼容正則表達式的語法規則匹配,如果需要Nginx的Rewrite功能,在編譯Nginx之前,需要編譯安裝PCRE庫。通過Rewrite規則,可以實現規范的URL、根據變量來做URL轉向及選擇配置。
作用: 實現對URL的重寫以及對匹配(正則表達式)的url的重定向
場景:
1. URL訪問跳轉, 支持開發設計
① 頁面跳轉 ② 兼容性支持 ③ 展示效果
2. SEO優化
3. 維護
① 后臺維護 ② 流量轉發
4. 安全
① 偽靜態頁面
配置語法
systax: rewrite [正則表達式 替換前的URL] [替換后的URL] [標識];
default: 無配置
指令 | 默認值 | 使用范圍 | 作用 |
---|---|---|---|
break | none | if,server,location | 完成當前的規則集,不再處理rewrite指令,需要和last加以區分 |
if ( condition ) { … } | none | server,location | 用于檢測一個條件是否符合,符合則執行大括號內的語句。不支持嵌套,不支持多個條件&&或處理 |
return | none | server,if,location | 用于結束規則的執行和返回狀態碼給客戶端。狀態碼的值可以是204,400,402,406,408,410,411,413,416以及500~504,另外非標準狀態碼444,表示以不發送任何的Header頭來結束連接。 |
rewrite regex replacement flag | server,location,if | 該指令根據表達式來重定向URI,或者修改字符串。 指令根據配置文件中的順序來執行。注意重寫表達式只對相對路徑有效。該指令根據表達式來重定向URI,或者修改字符串。指令根據配置文件中的順序來執行。注意重寫表達式只對相對路徑有效。 | |
uninitialized_variable_warn on/off | on | http,server,location,if | 該指令用于開啟和關閉未初始化變量的警告信息,默認值為開啟。 |
set variable value | none | 該指令用于定義一個變量,并且給變量進行賦值。 變量的值可以是文本、一個變量或者變量和文本的聯合,文本需要用引號引起來。 |
1、rewrite指令語法
指令語法: rewrite regex replacement [flag]
默認值: none
應用位置:server、location、if
rewrite是實現URL重寫的關鍵指令,根據regex(正則表達式)部分的內容,重定向到replacement部分,結尾是flag標記。
下面是一個簡單地URL rewrite跳轉的例子:
rewrite ^/(.*) http://www.sztqnet.com/$1 permanent;
在上述指令中,rewrite為固定關鍵字,表示開啟一條rewrite匹配規則,regex部分是^/(.*),這是一個正則表達式,表示匹配所有,匹配成功后跳轉到http://www.sztqnet.com/$1。這里的$1是取前面regex部分括號里的內容結尾的permanent;是永久301重定向標記,即跳轉到后面的http://www.sztqnet.com/$1地址上。
2、rewrite指令結尾的flag標記說明
flag標記符號 | 說 明 |
---|---|
last | 本條規則匹配完成后,繼續向下匹配新的location URI規則 |
break | 本條規則匹配完成即終止,不再匹配后面的任何規則 |
redirect | 返回302臨時重定向,瀏覽器地址欄會顯示跳轉后的URL地址 |
permanent | 返回301永久重定向,瀏覽器地址欄會顯示跳轉后的URL地址 |
在以上的flag標記中,last和break用來實現URL重寫,瀏覽器地址欄的URL地址不變,但在服務器訪問的程序及路徑發生了變化。redirect和permanent用來實現URL跳轉,瀏覽器地址會顯示跳轉后的URL地址。
last和break標記的實現功能類似,但二者之間有細微的差別,使用alias指令時必須用last標記,使用proxy_pass指令時要使用break標記。
last標記在本條rewrite規則執行完畢后,會對其所在的server{…}標簽重新發起請求,而break標記則會在本條規則匹配完成后,終止匹配,不再匹配后面的規則。
1、 break
參數項:break,用于停止執行rewrite模塊的指令,但是其他模塊不受影響。
配置位置:server,location,if
示例
server { listen 80; server_name localhost; #===== break && rewrite test ===== #這里如果注釋掉break,所有請求進來都是返回http200,this is breaktest... break; return 200 "this is breaktest..."; location = /breaktest { break; return 200 $request_uri; proxy_pass http://192.168.88.38/other; } location / { return 200 $request_uri; } } # 發送請求如下 # curl 127.0.0.1:8080/testbreak # /other # 可以看到 返回 `/other` 而不是 `/testbreak`,說明 `proxy_pass` 指令還是被執行了 # 也就是說 其他模塊的指令是不會被 break 中斷執行的 #(proxy_pass是ngx_http_proxy_module的指令)
測試鏈接:http://192.168.88.38/breaktest ,請求到達server塊后,被break終止執行rewrite指令集,return屬于rewrite模塊指令集,所以return 200 “this is breaktest…”不會執行;
因為沒有返回結果,所以繼續執行location匹配,請求匹配到location = /breaktest{}之后,break終止return 200 $request_uri,而proxy_pass屬于ngx_http_proxy_module,仍會繼續執行,
反向代理后的新url匹配到location /{},因此最終返回結果為 http200,/other,如下圖:
2、set
配置位置:server,location,if,用于為變量賦值
示例:
server { listen 80; server_name localhost; #===== break && rewrite test ===== #這里如果注釋掉break,所有請求進來都是返回http200,this is breaktest... break; return 200 "this is breaktest..."; location = /breaktest { break; return 200 $request_uri; proxy_pass http://192.168.88.38/other; } location / { #set賦值,可以直接賦字符串,或是變量,如下是變量和字符串的組合 set $set_value_test “112233 $request_uri”; return 200 $set_value_test; } }
測試鏈接http://192.168.88.38/breaktest,使用效果如下圖:
3.if
配置位置:server,location,用于依據指定的條件,決定是否執行if塊中的語句
判斷條件:
3.1.變量值為空或為0,都為false;
示例:
set $if_value_test “0”; #注意這里if、()和{}要空格,否則會報錯..略坑,不過這也是代碼規范了 if ($if_value_test) { #不會執行,因為$if_value_test值為0,false return 200; }
3.2.變量與字符串比較,=為等于,!=為不等
3.3.變量與正則表達式匹配,~ 為區分大小寫匹配,~* 為不區分大小寫匹配,!~ , !~*前面兩者的非操作
示例:
if ($request_uri ~ “^/breaktest$”) { #測試鏈接http://192.168.88.38/breaktest,最終返回http200 return 200; }
3.4.檢查文件是否存在,-f存在即為true,!-f不存在即為true
3.5.檢查目錄是否存在,-d存在即為true,!-d不存在即為true
3.6.檢查文件或目錄是否存在,-e存在即為true,!-e不存在即為true
3.7.檢查文件是否可執行,-x可執行即為true,!-x不可執行即為true
示例:
if (-e /usr/local/nginx/conf) { return 200; }
其他示例:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; } //如果UA包含"MSIE",rewrite請求到/msid/目錄下 if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; } //如果cookie匹配正則,設置變量$id等于正則引用部分 if ($request_method = POST) { return 405; } //如果提交方法為POST,則返回狀態405(Method not allowed)。return不能返回301,302 if ($slow) { limit_rate 10k; } //限速,$slow可以通過 set 指令設置 if (!-f $request_filename){ break; proxy_pass http://127.0.0.1; } //如果請求的文件名不存在,則反向代理到localhost 。這里的break也是停止rewrite檢查 if ($args ~ post=140){ rewrite ^ http://mysite.com/ permanent; } //如果query string中包含"post=140",永久重定向到mysite.com
if指令中,可以使用全局變量,這些變量有:
$ args: #這個變量等于請求行中的參數,同$query_string
$ content_length: 請求頭中的Content-length字段。
$content_type: 請求頭中的Content-Type字段。
$document_root: 當前請求在root指令中指定的值。
$host: 請求主機頭字段,否則為服務器名稱。
$http_user_agent: 客戶端agent信息
$http_cookie: 客戶端cookie信息
$limit_rate: 這個變量可以限制連接速率。
$request_method: 客戶端請求的動作,通常為GET或POST。
$remote_addr: 客戶端的IP地址。
$remote_port: 客戶端的端口。
$remote_user: 已經經過Auth Basic Module驗證的用戶名。
$request_filename: 當前請求的文件路徑,由root或alias指令與URI請求生成。
$scheme: HTTP協議(如http,https)。
$server_protocol: 請求使用的協議,通常是HTTP/1.0或HTTP/1.1。
$server_addr: 服務器地址,在完成一次系統調用后可以確定這個值。
$server_name: 服務器名稱。
$server_port: 請求到達服務器的端口號。
$request_uri: 包含請求參數的原始URI,不包含主機名,如:”/foo/bar.php?arg=baz”。
$ uri: 不帶請求參數的當前URI,$uri不包含主機名,如”/foo/bar.html”。
$ document_uri: 與$uri相同。
4.return
配置位置:server,location,if
參數值:return code [text]返回狀態碼及文本、return url重定向、return code url重定向
5.rewrite
配置位置:server,location,if
參數值:rewrite regex replacement [flag],用于以正則表達式匹配特定格式的url并重寫url.
regex為正則表達式,replacement為重寫的內容,flag為rewrite的標識位
replacement:重寫的url帶http,表示重定向
示例:
location / { #測試鏈接http://192.168.88.38/test/,被重定向到百度首頁,后面的語句不會再執行 rewrite /test/(.*) http://www.baidu.com; set $set_value_test "112233 $request_uri"; return 200 $set_value_test; }
replacement:重寫的url不帶http,單純的重寫url
示例:
location / { #測試鏈接http://192.168.88.38/test/,匹配到location /{}后url被重寫為http://192.168.88.38/breaktest,繼續搜索匹配 #匹配到location = /breaktest{},最終返回http200及this is breaktest rewrite /test/(.*) /breaktest; } location = /breaktest { return 200 "this is breaktest"; }
6、flag
flag:用于設置重寫url后的進一步操作,有break,last,redirect,permanent,rewrite不帶flag時,多個rewrite指令順序執行,當location中沒有可執行的rewrite模塊指令時,重新發起一次location匹配,下面說明各個flag的用途:
break:和上面講的break用途及用法一樣,終止執行rewrite模塊指令集;
last:終止執行rewrite模塊指令集,并開始搜尋重寫url后匹配的location;
redirect:臨時重定向
permanent:永久重定向
示例:
location / { #測試鏈接http://192.168.88.38/test1,匹配到location / {} rewrite ^/test1 /test2;#被重寫為/test2,繼續往下執行rewrite rewrite ^/test2 /test3;#被重寫為/test3,往下沒有可執行的rewrite模塊指令,發起一次location匹配,匹配到location /test3 {},最終返回http200及/test3 } location /test2 { return 200 "/test2"; } location /test3 { return 200 "/test3"; }
last和break的區別在于,last會發起新的location匹配,而break不會。
示例:
location / { rewrite ^/test1 /test2; rewrite ^/test2 /test3 last; rewrite ^/test3 /test4; } location /test2 { return 200 "/test2"; } location /test3 { return 200 "/test3"; } location /test4 { return 200 "/test4"; }
測試鏈接:http://192.168.88.38/test1 匹配到 location / {}后,被重寫為/test2,順序執行再次被重寫為/test3,因為flag為last,所以不會繼續重寫為/test4,而是發起一次location匹配,匹配到location /test3{},所以最終返回結果為http200及/test3;
如果把location /{}中的last改為break,被重寫為/test3后,不再重寫為/test4,也不會發起location,最終沒有可匹配的資源,返回http404。
7、正則匹配URL的參數傳遞
小括號()之間匹配的內容,可以在后面通過 $下標 來引用,如1 表 示 引 用 第 一 個 小 括 號 匹 配 的 內 容 , 1表示引用第一個小括號匹配的內容,1表示引用第一個小括號匹配的內容,表示引用第二個小括號匹配的內容。
示例:
location / { rewrite ^/(test1)/(test2)/(test3) /$2/$3; return 200 $2-$3; }
最終返回結果: