本文目錄: 1.1 URL重寫簡介1.2 if指令1.3 rewrite指令1.4 URL重寫和反向代理的區別 1.1 簡介 url重寫由ngx_http_rewrite_module模塊提供,預設會安裝,但該模塊功能的實現需要pcre。URL重寫技術不僅要求掌握幾個指令的語法、熟悉簡單的正則表達式 ...
1.1 URL重寫簡介
1.2 if指令
1.3 rewrite指令
1.4 URL重寫和反向代理的區別
1.1 簡介
url重寫由ngx_http_rewrite_module模塊提供,預設會安裝,但該模塊功能的實現需要pcre。URL重寫技術不僅要求掌握幾個指令的語法、熟悉簡單的正則表達式,還需要儘量熟悉nginx的各個變數的意義,熟悉的變數越多越好。大多數需要用到的變數都是http_core模塊提供的,它們的意義參見官方手冊http_core內置變數。
rewrite模塊主要有break、return、set、rewrite和if這5個指令。
- break的作用是完成當前的作用集,不再執行rewrite指令
- return返回狀態碼。可用的狀態碼有204/301/302/303/307/308/400/402-406/408/410-411/413/416/500-504。return三種語法:
return code [text]; return code URL; return URL;
- set用於定義變數。賦給變數的值可以是一個變數、文本及文本變數的組合(語法:set variable value;)
- if用於設定判斷條件。格式為if (condition) {}
- rewrite用於設定URL重寫規則(語法:rewrite regex replacement [flag];)
1.2 if指令
if不支持嵌套,不支持"&&"和"||"多目運算符。語法為:
if (condition) {}
測試條件可以如下定義:
(1). 變數的比較可以使用"="和"!="運算符。
(2). 正則匹配可以使用"~"和"~*",前者表示區分大小寫的正則匹配,後者表示不區分大小寫的匹配。
(3). 正則匹配可以在前面加上感嘆號"!~"和"!~*"表示取反,即不匹配。
(4). "-f"和"!-f"判斷文件是否存在。
(5). "-d"和"!-d"判斷目錄是否存在。
(6). "-e"和"!-e"判斷文件或目錄或軟鏈接是否存在。
(7). "-x"和"!-x"判斷文件是否可執行。
if支持的正則表達式可以使用$1至$9來實現反向引用。
以下為幾個示例:
# 當使用IE瀏覽器訪問時,重定向到/msie/目錄下的對應文件
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
# 當http請求的方法為POST,則直接返回405狀態碼,即Method not Allowed
if ($request_method = POST) {
return 405;
}
# 當請求的資源文件不存在,則直接退出當前匹配,並代理至本機,這種情況下由本機來提供服務,如提供錯誤頁面
if (!-f $request_filename) {
break;
proxy_pass http://127.0.0.1;
}
# 當訪問的是longshuai.com下任意主機,則重定向到www.longshuai.com主機下的對應目錄
if ($http_host ~* "^(.*)\.longshuai\.com$") {
set $domain $1;
rewrite ^(.*) http://www.longshuai.com/$domain/ break;
}
上面最後一種URL重寫後的URL為一個新的主機名站點,但使用URL重寫的效率比較低下,遠不如直接為此站點獨立定義一個虛擬主機。所以改寫為:
server {
listen 80;
server_name .longshuai.com;
return 302 http://www.longshuai.com/$request_uri;
}
server {
listen 80;
server_name www.longshuai.com;
}
1.3 rewrite指令
rewrite可以寫在server段、location段和if段。語法:
rewrite regexp replacement [flag]
如果replacement部分以"http://"或"https://"或"$schema"開頭,則直接臨時重定向,見下表中的redirect標記。
flag是標記。有4種標記,它們的作用如下表。
flag | 說明 |
---|---|
last | 停止處理當前上下文中的其他重寫模塊指令,併為重寫後的uri再次進行上下文的匹配 |
break | 和break指令一樣,都是停止處理當前上下文中的其他重寫模塊指令 |
redirect | 返回臨時重定向狀態碼302。當replacement部分不是以"http://"或者"https://"或者"$schema"開頭的時候使用,"$schema"變數表示使用的是什麼協議 |
permanent | 返回永久重定向狀態碼301 |
以上flag中,last和break用來實現URL改寫,此時瀏覽器中的地址不會改變,但實際上在伺服器上訪問的資源和路徑已經改變了。redirect和permanent用來實現URL跳轉,瀏覽器中的地址會改變為跳轉後的地址。
在使用proxy_pass指令時要使用break標記。last標記在本條rewrite規則執行完後,繼續在當前上下文對重寫後的地址發起匹配請求,而break則在本次匹配完成後停止再次匹配。例如下麵的兩條重寫規則。
rewrite "^/bbs/(.*)/images/(.*)\.jpg$" www.longshuai.com/bbs/$2/images/$1.jpg last;
rewrite "^/bbs/(.*)/images/(.*)\.jpg$" www.longshuai.com/bbs/$2/images/$1.jpg break;
如果訪問的是www.longshuai.com/bbs/a/images/b.jpg則重寫後為www.longshuai.com/bbs/b/images/a.jpg,但是重寫後的地址仍然可以匹配到規則^/bbs/(.*)/images/(.*)\.jpg$
,此時如果使用last標記,則會再次進行重寫,最終導致URL重寫迴圈,nginx預設支持10次迴圈,然後返回500狀態碼。而如果使用break標記,則在重寫完成後不會再次匹配重寫。
例如,下麵的重寫示例將會使得任意以longshuai.com結尾的訪問重定向到www.longshuai.com。
server_name www.longshuai.com;
rewrite (.*).longshuai.com www.longshuai.com permanent;
下麵的重寫實例將使得www.longshuai.com/bbs/*的訪問都重定向到www.longshuai.com/forum/*。
server {
listen 80;
server_name www.longshuai.com;
location /{
root /www/longshuai/;
index index.html;
rewrite "/bbs/(.*)" "/forum/$1" last;
}
}
1.4 URL重寫和反向代理的區別
URL重寫和反向代理都能將請求轉發到其他主機上。但它們有很大的區別。
1.URL重寫可以實現一些反向代理不能實現的轉發。
2.URL重寫可以實現瀏覽器地址改變。
3.反向代理更多的配合upstream實現負載均衡。URL重寫無法直接通過轉發實現負載均衡。
4.還有很多其他的區別,無需關心它們的區別,當某種需求既可以URL重寫實現,也可以反向代理實現,隨便用一種方法即可。