一篇文章說透Nginx的rewrite模組
文章出處:米粒人生---
rewrite模組即ngx_http_rewrite_module
模組,主要功能是改寫請求URI,是Nginx預設安裝的模組。rewrite模組會根據PCRE正則匹配重寫URI,然後發起內部跳轉再匹配location,或者直接做30x重定向返回客戶端。
rewrite指令的工作原理
rewrite模組的指令有break, if, return, rewrite, set等。rewrite指令所執行的順序如下:
首先在server上下文中依照順序執行rewrite模組指令;
如果server中行了rewrite重寫,那麼以新URI發起內部跳轉,直接匹配location,不會再執行server裡的rewrite指令,然後
新URI直接匹配location
如果匹配上某個location,那麼其中的rewrite模組指令同樣依照順序執行
如果再次導致URI的rewrite,那麼再一次進行內部跳轉去匹配location,但跳轉的總次數不能超過10次
rewrite
基本語法: rewrite regex replacement [flag];
上下文:server, location, if
regex是PCRE 風格的,如果regex匹配URI,那麼URI就會被替換成replacement,replacement 就是新的URI。如果rewrite同一個上下文中有多個這樣的正則,匹配會依照rewrite指令出現的順序先後依次進行下去,匹配到一個之後並不會終止,而是繼續往下匹配,直到返回最後一個匹配上的為止。如果想要中止繼續往下匹配,可以使用第三個引數flag。
如果新URI字元中有關於協議的任何東西,比如http://或者https://等,進一步的處理就終止了,直接返回客戶端302。
如果返回的是30x,那麼瀏覽器根據這個狀態碼和Location響應頭再發起一次請求,然後才能得到想要的響應結果。但是,如果不是返回30x狀態碼,那麼跳轉就是內部的,瀏覽器不做跳轉就能得到相應。
注意:regex直接就是正規表示式,不要再前面新增~符號
flag 引數可以有以下的一些值:
last
如果有last引數,那麼停止處理任何rewrite相關的指令,立即用替換後的新URI開始下一輪的location匹配
break
停止處理任何rewrite的相關指令,就如同break 指令本身一樣。
last的break的相同點在於,立即停止執行所有當前上下文的rewrite模組指令;不同點在於last引數接著用新的URI馬上搜尋新的location,而break不會搜尋新的location,直接用這個新的URI來處理請求,這樣能避免重複rewite。因此,在server上下文中使用last,而在location上下文中使用break。
redirect
replacement 如果不包含協議,仍然是一個新的的URI,那麼就用新的URI匹配的location去處理請求,不會返回30x跳轉。但是redirect引數可以讓這種情況也返回30x(預設302)狀態碼,就像新的URI包含http://和https://等一樣。這樣的話,瀏覽器看到302,就會再發起一次請求,真正返回響應結果的就是這第二個請求。
permanent
和redirect引數一樣,只不過直接返回301永久重定向
雖說URI有了新的,但是要拼接成完整的URL還需要當前請求的scheme,以及由server_name_in_redirect
和port_in_redirect
指令決定的HOST和PORT.
還有一個比較有意思的應用,就是如果replacement中包含請求引數,那麼預設情況下舊URI中的請求引數也會拼接在replacement後面作為新的URI,如果不想這麼做,可以在replacement的最後面加上?。
舉例說明:
rewrite ^/users/(.*)$ /show?user=$1? last;
這樣的新URI還是 /show?user=xxx
但如果不加問號:
rewrite ^/users/(.*)$ /show?user=$1 last;
得到的新URI就是/show?user=$1&xxx=xxx
。其中xxx=xxx是舊URI所帶的請求引數。
rewrite的例子
在server中使用的情況:
server { ... rewrite ^(/download/.*)/media/(.*)..*$ $1/mp3/$2.mp3 last; rewrite ^(/download/.*)/audio/(.*)..*$ $1/mp3/$2.ra last; return 403; #沒有匹配上,那就返回403咯 ... }
注意,在server中使用rewrite ,我們使用的flag是last,但是在location中,我們卻只能用break:
location /download/ { rewrite ^(/download/.*)/media/(.*)..*$ $1/mp3/$2.mp3 break; rewrite ^(/download/.*)/audio/(.*)..*$ $1/mp3/$2.ra break; return 403; }
如果在location的rewrite也使用last,便會再次以新的URI重新發起內部重定向,再次進行location匹配,而新的URI中極有可能和舊的URI一樣再次匹配到相同location中,這樣死迴圈發生了。當迴圈到第10次時,Nginx會終止這樣無意義的迴圈,並返回500錯誤。這點需要特別的注意。
break
基本語法:break;
上下文:server, location, if
停止處理任何rewrite的相關指令。如果出現在location裡面,那麼所有後面的rewrite模組指令都不會再執行,也不發起內部重定向,而是直接用新的URI進一步處理請求。
if
基本語法:if (condition) { ... }
上下文:server, location
根據條件condition的真假決定是否載入{...}中的配置,{...}中的配置可以繼承外面的配置,也可以對外面已有配置指令進行覆寫。
條件condition是針對變數而言的,變數既可以是系統變數,也可以是自定義的,可以是下面幾種情況:
當condition為變數
$var
本身時,當且僅當變數值為空字元或者0時,條件為false,其餘情況皆為 true變數
$var
透過"="或者"!="與字串相比較,即$var = xxx
或者$var != xxx
匹配一個正規表示式
-f
-d
-e
-x
等檢驗檔案或者目錄屬性或者存在與否的運算子
正則匹配
其中,對於 3. 匹配一個正規表示式的情況,可以細分為:
$var ~ Reg
表示大小寫敏感匹配$var ~* Reg
表示大小寫不敏感匹配$var !~ Reg
表示大小寫敏感不匹配$var !~* Reg
表示大小寫不敏感不匹配
Reg 中可以捕獲變數,當其中包含有 } 或者 ; 時需要用雙引號或者單引號括起來。
檔案檢驗
另外,對於 4. 檢驗檔案存在或者屬性的情況,具體說來也分為以下幾種:
-f /path/to 檢驗檔案是否存在;!-f /path/to 檢驗檔案是否不存在
-d /path/to/ 檢驗目錄是否存在;!-d /path/to/ 檢驗目錄是否不存在
-e /path/to/ 檢驗檔案或者目錄或者連結是否存在;!-e /path/to/ 檢驗檔案或者目錄或者連結是否不存在
-x /path/to 檢驗檔案是否為可執行檔案;!-x /path/to 檢驗檔案是否為不可執行檔案
if 指令舉例
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; } location /xiao/ { if ($http_user_agent ~ Mozilla/5.0) { #如果是chrom瀏覽器 rewrite ^(.*)$ #返回客戶端302 } if ($http_user_agent ~ curl) { # 如果是curl 發起請求 rewrite ^/xiao/(.*)$ /xiao/$1.txt break; #得到新的URI } } if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; #提取了變數$1}if ($request_method = POST) { return 405; #可以限制Request Method}if ($slow) { limit_rate 10k; #這個配置會加在location裡面}if ($invalid_referer) { return 403; }
return
基本語法:return code [text];或者return code URL;或者return URL;
上下文:server, location, if
停止任何的進一步處理,並且將指定狀態碼返回給客戶端。如果狀態碼為444(此狀態碼是非標準的),那麼直接關閉此TCP連線。
return的引數有四種形式:
return code
此時,響應內容就是nginx所預設的,比如503 Service Temporarily Unavailable; 如果是444那就直接關閉TCP連線,也可以是其他值(644等),但是沒啥意義return code text
因為要帶響應內容,因此code不能是具有跳轉功能的30xreturn code URL
此時URI可以為URI做內部跳轉,也可以是具有“, 302, 303, 307,308)return URL
此時code預設為302,而URL必須是帶“
set
基本語法:set $variable value;
上下文:server, location, if
這是一個有用的指令,用來定義變數,變數的值可以包含字串,另外的變數或者是二者結合。
set $var = $http_x_forwarded_for;
注意:在Nginx中,除非特殊說明,大部分地方字串的不需要引號括住,字串和變數的拼接也不需要引號
rewrite_log
基本語法:rewrite_log on | off;
上下文:http, server, location, if
如果開啟 on,那麼當發生rewrite時,會產生一個notice級別的日誌;否則不會產生任何日誌。預設情況下是不產生的,但在除錯的時候可以將其置為on。
以上這些指令,基本涵蓋了rewrite模組的所有應用,在需要改寫請求URI,或者做跳轉時非常有用。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4686/viewspace-2808594/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Nginx 學習總結(4)—— Rewrite 模組Nginx
- nginx學習-ngx_http_rewrite_module模組NginxHTTP
- mod_rewrite模組
- nginx事件模組 -- 第一篇Nginx事件
- nginx rewriteNginx
- Nginx RewriteNginx
- 一篇文章玩透awk
- Nginx rewrite 詳解Nginx
- Nginx常用的模組Nginx
- 10、一篇經典的域滲透文章
- nginx thinkphp rewrite配置項NginxPHP
- nginx rewrite語法格式Nginx
- nginx高階篇rewriteNginx
- 一篇講透:模組典型上網業務的AT上網流程
- 一篇文章說清楚基因組結構性變異檢測的方法
- 循序漸進nginx(三):日誌管理、http限流、https配置,http_rewrite模組,第三方模組安裝,結語NginxHTTP
- Nginx 實現 Rewrite 跳轉Nginx
- 為 Nginx 新增模組Nginx
- Nginx 新增 lua 模組Nginx
- nginx location匹配及rewrite規則Nginx
- Nginx location匹配及Rewrite重寫Nginx
- Tengine新增nginx upstream模組的使用Nginx
- Nginx安裝nginx-rtmp-module模組Nginx
- nginx學習之模組Nginx
- 一文說透WordPress的自定義文章型別型別
- Nginx Rewrite實際應用配置解析Nginx
- Nginx的ngx_http_fastcgi_module模組NginxHTTPAST
- Nginx使用SSL模組配置httpsNginxHTTP
- Nginx的HTTP模組與Stream模組:區別與應用場景NginxHTTP
- 一篇文章讓你學透Linux系統中的more命令Linux
- NGINX使用rewrite實現http 跳轉 httpsNginxHTTP
- [LearnKu 更新] 新增「文章推薦」模組
- 一篇文章講透Dijkstra最短路徑演算法演算法
- Nginx原始碼研究之nginx限流模組詳解Nginx原始碼
- Nginx為已安裝nginx動態新增模組Nginx
- Profinet遠端IO模組:模擬量模組_軟體組態說明
- nginx事件模組 -- 第二篇Nginx事件
- nginx使用熱部署新增新模組Nginx熱部署