ngxhttprewrite_module 模塊用來使用正則表達式(PCRE)改變請求的 URI,返回重定向,并有條件地選擇配置。
指令執行順序
-
首先順序執行 server 塊中的 rewrite 模塊指令,得到 rewrite 后的請求 URI
-
然后循環執行如下指令 > 如果沒有遇到中斷循環標志,此循環最多執行 10 次,但是我們可以使用 break 指令來中斷 rewrite 后的新一輪的循環
(1). 依據 rewrite 后的請求 URI,匹配定義的 location 塊
(2). 順序執行匹配到的 location 中的 rewrite 模塊指令
指令
break
Context: server, location, if
停止執行 ngxhttprewrite_module 的指令集,但是其他模塊指令是不受影響的 例子說明
-
server {
-
? ?listen 8080;
-
? ?# 此處 break 會停止執行 server 塊的 return 指令(return 指令屬于 rewrite 模塊)
-
? ?# 如果把它注釋掉 則所有請求進來都返回 ok
-
? ?break;
-
? ?return 200 "ok";
-
? ?location = /testbreak {
-
? ? ? ?break;
-
? ? ? ?return 200 $request_uri;
-
? ? ? ?proxy_pass http://127.0.0.1:8080/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的指令)
if
Context: server, location
依據指定的條件決定是否執行 if 塊語句中的內容
if 中的幾種 判斷條件
-
一個?
變量名
,如果變量 $variable 的值為空字符串或者字符串"0",則為 false -
變量
與一個字符串的比較 相等為(=) 不相等為(!=)?注意此處不要把相等當做賦值語句啊
-
變量
與一個正則表達式的模式匹配 操作符可以是(?~
?區分大小寫的正則匹配,?~*
不區分大小寫的正則匹配,?!~
?!~*
,前面兩者的非) -
檢測文件是否存在 使用?
-f
(存在) 和?!-f
(不存在) -
檢測路徑是否存在 使用?
-d
(存在) 和?!-d
(不存在) 后面判斷可以是字符串也可是變量 -
檢測文件、路徑、或者鏈接文件是否存在 使用?
-e
(存在) 和?!-e
(不存在) 后面判斷可以是字符串也可是變量 -
檢測文件是否為可執行文件 使用?
-x
(可執行) 和?!-x
(不可執行) 后面判斷可以是字符串也可是變量
注意 上面 第1,2,3條被判斷的必須是 變量, 4, 5, 6, 7則可以是變量也可是字符串
-
set $variable "0";
-
if ($variable) {
-
? ?# 不會執行,因為 "0" 為 false
-
? ?break; ? ? ? ? ? ?
-
}
-
?
-
# 使用變量與正則表達式匹配 沒有問題
-
if ( $http_host ~ "^star\.igrow\.cn$" ) {
-
? ?break; ? ? ? ? ? ?
-
}
-
?
-
# 字符串與正則表達式匹配 報錯
-
if ( "star" ~ "^star\.igrow\.cn$" ) {
-
? ?break; ? ? ? ? ? ?
-
}
-
# 檢查文件類的 字符串與變量均可
-
if ( !-f "/data.log" ) {
-
? ?break; ? ? ? ? ? ?
-
}
-
?
-
if ( !-f $filename ) {
-
? ?break; ? ? ? ? ? ?
-
}
return
Context: server, location, if
-
return code [text];
-
return code URL;
-
return URL;
停止處理并將指定的 code
碼返回給客戶端。 非標準 code
碼 444 關閉連接而不發送響應報頭。
從 0.8.42
版本開始, return
語句可以指定重定向 url
(狀態碼可以為如下幾種 301,302,303,307), 也可以為其他狀態碼指定響應的文本內容,并且重定向的 url
和響應的文本可以包含 變量
。
有一種特殊情況,就是重定向的 url
可以指定為此服務器本地的 urI
,這樣的話, nginx
會依據請求的協議 $scheme
, server_name_in_redirect
和 port_in_redirect
自動生成完整的 url
(此處要說明的是 server_name_in_redirect
和 port_in_redirect
指令是表示是否將 server
塊中的 server_name
和 listen
的端口 作為 redirect
用 )
-
# return code [text]; 返回 ok 給客戶端
-
location = /ok {
-
? ?return 200 "ok";
-
}
-
?
-
# return code URL; 臨時重定向到 百度
-
location = /redirect {
-
? ?return 302 http://www.baidu.com;
-
}
-
?
-
# return URL; 和上面一樣 默認也是臨時重定向
-
location = /redirect {
-
? ?return http://www.baidu.com;
-
}
rewrite
Context: server, location, if
-
rewrite regex replacement [flag];
rewrite
指令是使用指定的正則表達式 regex
來匹配請求的 urI
,如果匹配成功,則使用 replacement
更改 URI
。 rewrite
指令按照它們在配置文件中出現的順序執行。可以使用 flag
標志來終止指令的進一步處理。如果替換字符串 replacement
以 http://
, https://
或 $ scheme
開頭,則停止處理后續內容,并直接重定向返回給客戶端。
第一種情況 重寫的字符串 帶 http://
-
location / {
-
? ?# 當匹配 正則表達式 /test1/(.*)時 請求將被臨時重定向到 http://www.$1.com
-
? ?# 相當于 flag 寫為 redirect
-
? ?rewrite /test1/(.*) http://www.$1.com;
-
? ?return 200 "ok";
-
}
-
# 在瀏覽器中輸入 127.0.0.1:8080/test1/baidu
-
# 則臨時重定向到 www.baidu.com
-
# 后面的 return 指令將沒有機會執行了
第二種情況 重寫的字符串 不帶 http://
-
location / {
-
? ?rewrite /test1/(.*) www.$1.com;
-
? ?return 200 "ok";
-
}
-
# 發送請求如下
-
# curl 127.0.0.1:8080/test1/baidu
-
# ok
-
?
-
# 此處沒有帶http:// 所以只是簡單的重寫。請求的 uri 由 /test1/baidu 重寫為 www.baidu.com
-
# 因為會順序執行 rewrite 指令 所以 下一步執行 return 指令 響應了 ok
rewrite 的四個 flag
-
last
?停止處理當前的?ngx_http_rewrite_module
的指令集,并開始搜索與更改后的?URI
相匹配的?location
; -
break
?停止處理當前的?ngx_http_rewrite_module
指令集,就像上面說的?break
指令一樣; -
redirect
?返回302臨時重定向。 -
permanent
?返回301永久重定向。?
-
# 沒有rewrite 后面沒有任何 flag 時就順序執行
-
# 當 location 中沒有 rewrite 模塊指令可被執行時 就重寫發起新一輪location匹配
-
location / {
-
? ?# 順序執行如下兩條rewrite指令
-
? ?rewrite ^/test1 /test2;
-
? ?rewrite ^/test2 /test3; ?# 此處發起新一輪location匹配 uri為/test3
-
}
-
?
-
location = /test2 {
-
? ?return 200 "/test2";
-
} ?
-
?
-
location = /test3 {
-
? ?return 200 "/test3";
-
}
-
# 發送如下請求
-
# curl 127.0.0.1:8080/test1
-
# /test3
last 與 break 的區別
last 和 break一樣 它們都會終止此 location 中其他它rewrite模塊指令的執行, 但是 last 立即發起新一輪的 location 匹配 而 break 則不會
-
location / {
-
? ?rewrite ^/test1 /test2;
-
? ?rewrite ^/test2 /test3 last; ?# 此處發起新一輪location匹配 uri為/test3
-
? ?rewrite ^/test3 /test4;
-
? ?proxy_pass http://www.baidu.com;
-
}
-
?
-
location = /test2 {
-
? ?return 200 "/test2";
-
} ?
-
?
-
location = /test3 {
-
? ?return 200 "/test3";
-
}
-
location = /test4 {
-
? ?return 200 "/test4";
-
}
-
# 發送如下請求
-
# curl 127.0.0.1:8080/test1
-
# /test3
-
?
-
當如果將上面的 location / 改成如下代碼
-
location / {
-
? ?rewrite ^/test1 /test2;
-
? ?# 此處 不會 發起新一輪location匹配;當是會終止執行后續rewrite模塊指令 重寫后的uri為 /
-
? ?rewrite ^/test2 /more/index.html break; ?
-
? ?rewrite /more/index\.html /test4; # 這條指令會被忽略
-
?
-
? ?# 因為 proxy_pass 不是rewrite模塊的指令 所以它不會被 break終止
-
? ?proxy_pass https://www.baidu.com;
-
}
-
# 發送如下請求
-
# 瀏覽器輸入 127.0.0.1:8080/test1
-
# 代理到 百度產品大全頁面 https://www.baidu.com/more/index.html;
友情提醒下
此處提一下 在上面的代碼中即使將 proxy_pass
放在 帶有 break
的 rewrite
上面它也是會執行的,這就要扯到 nginx
的執行流程了。大家有興趣可以了解下。
rewrite 后的請求參數
如果替換字符串 replacement
包含新的請求參數,則在它們之后附加先前的請求參數。如果你不想要之前的參數,則在替換字符串 replacement
的末尾放置一個問號,避免附加它們。
-
# 由于最后加了個 ?,原來的請求參數將不會被追加到rewrite之后的url后面
-
rewrite ^/users/(.*)$ /show?user=$1? last;
rewrite_log
Context: http, server, location, if
開啟或者關閉 rewrite
模塊指令執行的日志,如果開啟,則重寫將記錄下 notice
等級的日志到 nginx
的 error_log
中,默認為關閉 off
-
Syntax: ? ?rewrite_log on | off;
set
Context: server, location, if
設置指定變量的值。變量的值可以包含文本,變量或者是它們的組合形式。
-
location / {
-
? ?set $var1 "host is ";
-
? ?set $var2 $host;
-
? ?set $var3 " uri is $request_uri";
-
? ?return 200 "response ok $var1$var2$var3";
-
}
-
# 發送如下請求
-
# curl 127.0.0.1:8080/test
-
# response ok host is 127.0.0.1 uri is /test
uninitializedvariablewarn
Context: http, server, location, if
控制是否記錄 有關未初始化變量的警告。默認開啟