七,、Nginx之URL重寫
1.URL重寫模塊(Rewrite)
摘要
這 個模塊允許使用正則表達式重寫URI(需PCRE庫),并且可以根據(jù)相關(guān)變量重定向和選擇不同的配置,。如果這個指令在server字段中指定,,那么將在被 請求的location確定之前執(zhí)行,如果在指令執(zhí)行后所選擇的location中有其他的重寫規(guī)則,,那么它們也被執(zhí)行,。如果在location中執(zhí)行這 個指令產(chǎn)生了新的URI,那么location又一次確定了新的URI,。這樣的循環(huán)可以最多執(zhí)行10次,,超過以后nginx將返回500錯誤。
指令
break
語法:break
默認值:none
使用字段:server, location, if
完成當(dāng)前設(shè)置的規(guī)則,,停止執(zhí)行其他的重寫指令,。
示例:
|
if ($slow) {
limit_rate 10k;
break ;
}
|
if
語法:if (condition) { … }
默認值:none
使用字段:server, location
注意:在使用if指令之前請查看if is evil page并且盡量考慮用try_files代替。
判斷一個條件,,如果條件成立,,則后面的大括號內(nèi)的語句將執(zhí)行,相關(guān)配置從上級繼承,。
可以在判斷語句中指定下列值:
-
一個變量的名稱,;不成立的值為:空字符傳”“或者一些用“0”開始的字符串。
-
一個使用=或者!=運算符的比較語句,。
-
使用符號~*和~模式匹配的正則表達式:
-
~為區(qū)分大小寫的匹配,。
-
~*不區(qū)分大小寫的匹配(firefox匹配FireFox),。
-
!~和!~*意為“不匹配的”。
-
使用-f和!-f檢查一個文件是否存在,。
-
使用-d和!-d檢查一個目錄是否存在,。
-
使用-e和!-e檢查一個文件,目錄或者軟鏈接是否存在,。
-
使用-x和!-x檢查一個文件是否為可執(zhí)行文件,。
正則表達式的一部分可以用圓括號,方便之后按照順序用$1-$9來引用,。
示例配置:
|
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/ $1 break ;
}
if ($http_cookie ~* "id=([^;] +)(?:;|$)" ) {
set $ id $1;
}
if ($request_method = POST ) {
return 405;
}
if (!-f $request_filename) {
break ;
proxy_pass http: //127 .0.0.1;
}
if ($slow) {
limit_rate 10k;
}
if ($invalid_referer) {
return 403;
}
if ($args ~ post=140){
rewrite ^ http: //example .com/ permanent;
}
|
內(nèi)置變量$invalid_referer用指令valid_referers指定。
return
語法:return code
默認值:none
使用字段:server, location, if
這個指令結(jié)束執(zhí)行配置語句并為客戶端返回狀態(tài)代碼,,可以使用下列的值:204,,400,402-406,,408,,410, 411, 413, 416與500-504。此外,,非標準代碼444將關(guān)閉連接并且不發(fā)送任何的頭部,。
rewrite
語法:rewrite regex replacement flag
默認值:none
使用字段:server, location, if
按照相關(guān)的正則表達式與字符串修改URI,指令按照在配置文件中出現(xiàn)的順序執(zhí)行,。
可以在重寫指令后面添加標記,。
如果替換的字符串以http://開頭,請求將被重定向,,并且不再執(zhí)行多余的rewrite指令,。
尾部的標記(flag)可以是以下的值:
-
last - 完成重寫指令,之后搜索相應(yīng)的URI或location,。
-
break - 完成重寫指令,。
-
redirect - 返回302臨時重定向,如果替換字段用http://開頭則被使用,。
-
permanent - 返回301永久重定向,。
注 意如果一個重定向是相對的(沒有主機名部分),nginx將在重定向的過程中使用匹配server_name指令的“Host”頭或者 server_name指令指定的第一個名稱,,如果頭不匹配或不存在,,如果沒有設(shè)置server_name,將使用本地主機名,,如果你總是想讓nginx 使用“Host”頭,,可以在server_name使用“*”通配符(查看http核心模塊中的server_name)。例如:
|
rewrite ^( /download/ .*) /media/ (.*)\..*$ $1 /mp3/ $2.mp3 last;
rewrite ^( /download/ .*) /audio/ (.*)\..*$ $1 /mp3/ $2.ra last;
return 403;
|
但是如果我們將其放入一個名為/download/的location中,,則需要將last標記改為break,,否則nginx將執(zhí)行10次循環(huán)并返回500錯誤。
|
location /download/ {
rewrite ^( /download/ .*) /media/ (.*)\..*$ $1 /mp3/ $2.mp3 break ;
rewrite ^( /download/ .*) /audio/ (.*)\..*$ $1 /mp3/ $2.ra break ;
return 403;
}
|
如果替換字段中包含參數(shù),那么其余的請求參數(shù)將附加到后面,,為了防止附加,,可以在最后一個字符后面跟一個問號:
|
rewrite ^ /users/ (.*)$ /show ?user=$1? last;
|
注意:大括號({和}),可以同時用在正則表達式和配置塊中,,為了防止沖突,,正則表達式使用大括號需要用雙引號(或者單引號)。例如要重寫以下的URL:
為:
|
/path/to/photos/12/1234/123456 .png
|
則使用以下正則表達式(注意引號):
1
|
rewrite "/photos/([0-9] {2})([0-9] {2})([0-9] {2})" /path/to/photos/ $1/$1$2/$1$2$3.png;
|
如果指定一個“,?”在重寫的結(jié)尾,,Nginx將丟棄請求中的參數(shù),即變量$args,,當(dāng)使用$request_uri或$uri&$args時可以在rewrite結(jié)尾使用“,?”以避免nginx處理兩次參數(shù)串。
在rewrite中使用$request_uri將www.example.com重寫到example.com:
|
server {
server_name www.example.com;
rewrite ^ http: //example .com$request_uri? permanent;
}
|
同樣,,重寫只對路徑進行操作,,而不是參數(shù),如果要重寫一個帶參數(shù)的URL,,可以使用以下代替:
|
if ($args ^~ post=100){
rewrite ^ http: //example .com /new-address .html? permanent;
}
|
注意$args變量不會被編譯,,與location過程中的URI不同(參考http核心模塊中的location)。
rewrite_log
語法:rewrite_log on | off
默認值:rewrite_log off
使用字段:server, location, if
變量:無
啟用時將在error log中記錄notice 標記的重寫日志,。
set
語法:set variable value
默認值:none
使用字段:server, location, if
指令設(shè)置一個變量并為其賦值,,其值可以是文本,變量和它們的組合,。
你可以使用set定義一個新的變量,,但是不能使用set設(shè)置$http_xxx頭部變量的值。
uninitialized_variable_warn
語法:uninitialized_variable_warn on|off
默認值:uninitialized_variable_warn on
使用字段:http, server, location, if
開啟或關(guān)閉在未初始化變量中記錄警告日志,。
事實上,,rewrite指令在配置文件加載時已經(jīng)編譯到內(nèi)部代碼中,在解釋器產(chǎn)生請求時使用,。
這個解釋器是一個簡單的堆棧虛擬機,,如下列指令:
|
location /download/ {
if ($forbidden) {
return 403;
}
if ($slow) {
limit_rate 10k;
}
rewrite ^/(download/.*) /media/ (.*)\..*$ /$1 /mp3/ $2.mp3 break ;
|
將被編譯成以下順序:
variable $forbidden
checking to zero
recovery 403
completion of entire code
variable $slow
checking to zero
checkings of regular excodession
copying "/"
copying $1
copying "/mp3/"
copying $2
copying ".mp3"
completion of regular excodession
completion of entire sequence
|
注意并沒有關(guān)于limit_rate的代碼,因為它沒有提及ngx_http_rewrite_module模塊,,“if”塊可以類似”location”指令在配置文件的相同部分同時存在,。
如果$slow為真,對應(yīng)的if塊將生效,,在這個配置中l(wèi)imit_rate的值為10k,。
指令:
|
rewrite ^/(download/.*) /media/ (.*)\..*$ /$1 /mp3/ $2.mp3 break ;
|
如果我們將第一個斜杠括入圓括號,則可以減少執(zhí)行順序:
|
rewrite ^( /download/ .*) /media/ (.*)\..*$ $1 /mp3/ $2.mp3 break ;
|
之后的順序類似如下:
|
checking regular excodession
copying $1
copying "/mp3/"
copying $2
copying ".mp3"
completion of regular excodession
completion of entire code
|
2.簡單案例
注,,由于配置文件內(nèi)容較多,,為了讓大家看著方便,,我們備份一下配置文件,打開一個新的配置文件,。
|
[root@nginx ~] # cd /etc/nginx/
[root@nginx nginx] # mv nginx.conf nginx.conf.proxy
[root@nginx nginx] # cp nginx.conf.bak nginx.conf
[root@nginx nginx] # vim /etc/nginx/nginx.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
rewrite ^ /bbs/ (.*)$ http: //192 .168.18.201 /forum/ $1;
}
}
|
準備forum目錄與測試文件
|
[root@web1 ~] # cd /var/www/html/
[root@web1 html] # ls
index.html
[root@web1 html] # mkdir forum
[root@web1 html] # cd forum/
[root@web1 forum] # vim index.html
<h1>forum page!< /h1 >
|
測試一下
好了,,下面我們來測試一下rewrite重寫。
3.重新加載一下配置文件
|
[root@nginx 63] # service nginx reload
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
4.測試一下
注,, 大家可以從圖中看出,,status code 302指的是臨時重定向,那就說明我們rewrite重寫配置成功,。大家知道302是臨時重定向而301是永久重定向,,那么怎么實現(xiàn)永久重定向呢。一般服 務(wù)器與服務(wù)器之間是臨時重定向,,服務(wù)器內(nèi)部是永久重定向,。下面我們來演示一下永久重定向。
5.配置永久重定向
|
[root@nginx nginx] # vim /etc/nginx/nginx.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
rewrite ^ /bbs/ (.*)$ /forum/ $1;
}
}
|
準備forum目錄與測試文件
|
[root@nginx ~] # cd /usr/html/
[root@nginx html] # ls
50x.html index.html
[root@nginx html] # mkdir forum
[root@nginx html] # cd forum/
[root@nginx forum] # vim index.html
<h1>192.168.18.208 forum page< /h1 >
|
6.重新加載一下配置文件
|
[root@nginx ~] # service nginx reload
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
7.測試一下
注,,大家從圖中可以看到,我們訪問bbs/是直接幫我們跳轉(zhuǎn)到forum/下,,這種本機的跳轉(zhuǎn)就是永久重定向也叫隱式重定向,。好了,rewrite重定向我們就說到這里了,,想要查詢更多關(guān)于重定向的指令請參考官方文檔,。最后,我們來說一下讀寫分離,。
八,、Nginx之讀寫分離
1.實驗拓撲
需求分析,前端一臺nginx做負載均衡反向代理,,后面兩臺httpd服務(wù)器,。整個架構(gòu)是提供BBS(論壇)服務(wù),有一需求得實現(xiàn)讀寫分離,,就是上傳附 件的功能,,我們上傳的附件只能上傳到Web1,然后在Web1上利用rsync+inotify實現(xiàn)附件同步,,大家都知道rsync+inotify只能 是主向從同步,,不能雙向同步。所以Web1可進行寫操作,,而Web2只能進行讀操作,,這就帶來讀寫分離的需求,下面我們就來說一下,,讀寫分離怎么實現(xiàn),。
2.WebDAV功能說明
WebDAV (Web-based Distributed Authoring and Versioning) 一種基于 HTTP 1.1協(xié)議的通信協(xié)議,。它擴展了HTTP 1.1,在GET,、POST,、HEAD等幾個HTTP標準方法以外添加了一些新的方法,使應(yīng)用程序可直接對Web Server直接讀寫,,并支持寫文件鎖定(Locking)及解鎖(Unlock),,還可以支持文件的版本控制。這樣我們就能配置讀寫分離功能了,,下面我 們來具體配置一下,。
3.修改配置文件
|
[root@nginx nginx] # vim /etc/nginx/nginx.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http: //192 .168.18.202;
if ($request_method = "PUT" ){
proxy_pass http: //192 .168.18.201;
}
}
}
|
4.重新加載一下配置文件
|
[root@nginx ~] # service nginx reload
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
5.配置httpd的WebDAV功能
|
[root@web1 ~] # vim /etc/httpd/conf/httpd.conf
|
注,在<Directory "/var/www/html">下啟用就行,。
6.重新啟動一下httpd
|
[root@web1 ~] # service httpd restart
停止 httpd: [確定]
正在啟動 httpd: [確定]
|
7.測試一下
|
[root@nginx ~] # curl http://192.168.18.201
<h1>web1. test .com< /h1 >
[root@nginx ~] # curl http://192.168.18.202
<h1>web2. test .com< /h1 >
|
注,,web1與web2訪問都沒問題。
|
[root@nginx ~] # curl -T /etc/issue http://192.168.18.202
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN" >
<html>< head >
<title>405 Method Not Allowed< /title >
< /head ><body>
<h1>Method Not Allowed< /h1 >
The requested method PUT is not allowed for the URL /issue .
<hr>
<address>Apache /2 .2.15 (CentOS) Server at 192.168.18.202 Port 80< /address >
< /body >< /html >
|
注,,我們上傳文件到,,web2上時,因為web2只人讀功能,,所以沒有開戶WebDAV功能,,所以顯示是405 Method Not Allowed。
|
[root@nginx ~] # curl -T /etc/issue http://192.168.18.201
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN" >
<html>< head >
<title>403 Forbidden< /title >
< /head ><body>
<h1>Forbidden< /h1 >
You don't have permission to access /issue
on this server.
<hr>
<address>Apache /2 .2.15 (CentOS) Server at 192.168.18.201 Port 80< /address >
< /body >< /html >
|
注,,我們在Web1開啟了WebDAV功能,,但我們目錄是root目錄是不允許apache用戶上傳的,所以顯示的是403 Forbidden,。下面我們給apache授權(quán),,允許上傳。
|
[root@web1 ~] # setfacl -m u:apache:rwx /var/www/html/
|
下面我們再來測試一下,,
|
[root@nginx ~] # curl -T /etc/issue http://192.168.18.201
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN" >
<html>< head >
<title>201 Created< /title >
< /head ><body>
<h1>Created< /h1 >
Resource /issue has been created.
<hr />
<address>Apache /2 .2.15 (CentOS) Server at 192.168.18.201 Port 80< /address >
< /body >< /html >
|
注,,大家可以看到我們成功的上傳了文件,說明nginx讀寫分離功能配置完成,。最后,,我們來查看一下上傳的文件。
|
[root@web1 ~] # cd /var/www/html/
[root@web1 html] # ll
總用量 12
drwxr-xr-x 2 root root 4096 9月 4 13:16 forum
-rw-r--r-- 1 root root 23 9月 3 23:37 index.html
-rw-r--r-- 1 apache apache 47 9月 4 14:06 issue
|
好了,,到這里nginx的反向代理,、負載均衡、頁面緩存,、URL重寫及讀寫分離就全部講解完成,。希望大家有所收獲,^_^……
原文地址:http://www./config/2015/1228/4216_7.html
|