這裏只是簡單記錄一些學習示例,高手略過,新手能夠看一下。php
Nginx Rewrite規則相關指令
Nginx Rewrite規則相關指令有if、rewrite、set、return、break等,其中rewrite是最關鍵的指令。一個簡單的Nginx Rewrite規則語法以下:css
rewrite ^/b/(.*)\.html /play.php?video=$1 break;
若是加上if語句,示例以下:html
if (!-f $request_filename) rewrite ^/img/(.*)$ /site/$host/p_w_picpaths/$1 last;
Nginx與Apache的Rewrite規則實例對比nginx
簡單的Nginx和Apache 重寫規則區別不大,基本上可以徹底兼容。例如:web
Apache Rewrite 規則:正則表達式
RewriteRule ^/(mianshi|xianjing)/$ /zl/index.php?name=$1 [L] RewriteRule ^/ceshi/$ /zl/ceshi.php [L] RewriteRule ^/(mianshi)_([a-zA-Z]+)/$ /zl/index.php?name=$1_$2 [L] RewriteRule ^/pingce([0-9]*)/$ /zl/pingce.php?id=$1 [L]
Nginx Rewrite 規則:
sql
rewrite ^/(mianshi|xianjing)/$ /zl/index.php?name=$1 last; rewrite ^/ceshi/$ /zl/ceshi.php last; rewrite ^/(mianshi)_([a-zA-Z]+)/$ /zl/index.php?name=$1_$2 last; rewrite ^/pingce([0-9]*)/$ /zl/pingce.php?id=$1 last;
由以上示例能夠看出,Apache的Rewrite規則改成Nginx的Rewrite規則,其實很簡單:Apache的RewriteRule指令換成Nginx的rewrite指令,Apache的[L]標記換成Nginx的last標記,中間的內容不變。apache
若是Apache的Rewrite規則改成Nginx的Rewrite規則後,使用nginx -t命令檢查發現nginx.conf配置文件有語法錯誤,那麼能夠嘗試給條件加上引號。例如一下的Nginx Rewrite規則會報語法錯誤:瀏覽器
rewrite ^/([0-9]{5}).html$ /x.jsp?id=$1 last;
加上引號就正確了:
緩存
rewrite 「^/([0-9]{5}).html$」 /x.jsp?id=$1 last;
Apache與Nginx的Rewrite規則在URL跳轉時有細微的區別:
Apache Rewrite 規則:
RewriteRule ^/html/tagindex/([a-zA-Z]+)/.*$ /$1/ [R=301,L]
Nginx Rewrite 規則:
rewrite ^/html/tagindex/([a-zA-Z]+)/.*$ http://$host/$1/ permanent;
以上示例中,咱們注意到,Nginx Rewrite 規則的置換串中增長了「http://$host」,這是在Nginx中要求的。
另外,Apache與Nginx的Rewrite規則在變量名稱方面也有區別,例如:
Apache Rewrite 規則:
RewriteRule ^/user/login/$ /user/login.php?login=1&forward=http://%{HTTP_HOST} [L]
Nginx Rewrite 規則:
rewrite ^/user/login/$ /user/login.php?login=1&forward=http://$host last;
Apache與Nginx Rewrite 規則的一些功能相同或相似的指令、標記對應關係:
Apache的RewriteCond指令對應Nginx的if指令;
Apache的RewriteRule指令對應Nginx的rewrite指令;
Apache的[R]標記對應Nginx的redirect標記;
Apache的[P]標記對應Nginx的last標記;
Apache的[R,L]標記對應Nginx的redirect標記;
Apache的[P,L]標記對應Nginx的last標記;
Apache的[PT,L]標記對應Nginx的last標記;
容許指定的域名訪問本站,其餘域名一概跳轉到http://www.aaa.com
Apache Rewrite 規則:
RewriteCond %{HTTP_HOST} ^(.*?)\.domain\.com$ RewriteCond %{HTTP_HOST} !^qita\.domain\.com$ RewriteCond %{DOCUMENT_ROOT}/market/%1/index.htm -f RewriteRule ^/wu/$ /market/%1/index.htm [L]
Nginx的if指令不支持嵌套,也不支持AND、OR等多條件匹配,相比於Apache的RewriteCond,顯得麻煩一些,可是,咱們能夠經過下一頁的Nginx配置寫法來實現這個示例:
Nginx Rewrite 規則:
if ($host ~* ^(.*?)\.domain\.com$) set $var_wupin_city $1; set $var_wupin ‘1′; if ($host ~* ^qita\.domain\.com$) set $var_wupin ‘0′; if (!-f $document_root/market/$var_wupin_city/index.htm) set $var_wupin ‘0′; if ($var_wupin ~ ‘1′) rewrite ^/wu/$ /market/$var_wupin_city/index.htm last;}
rewrite 的語法
用法: rewrite 正則 替換 標誌位
做用域: server, location, if
這個指令根據表達式來更改URI,或者修改字符串。指令根據配置文件中的順序來執行。
注意重寫表達式只對相對路徑有效。若是你想配對主機名,你應該使用if語句。
nginx的rewrite規則參考:
set
if
return
break
rewrite
麻雀雖小,五臟俱全.只是簡單的幾個指令卻能夠作出絕對不輸apache的簡單靈活的配置.
1.set 主要是用來設置變量用的,沒什麼特別的
2.if 主要用來判斷一些在rewrite語句中沒法直接匹配的條件,好比檢測文件存在與否,http header,cookie等,
用法: if(條件) {…}
- 當if表達式中的條件爲true,則執行if塊中的語句
- 當表達式只是一個變量時,若是值爲空或者任何以0開頭的字符串都會看成false
- 直接比較內容時,使用 = 和 !=
- 使用正則表達式匹配時,使用
~ 大小寫敏感匹配
~* 大小寫不敏感匹配
!~ 大小寫敏感不匹配
!~* 大小寫不敏感不匹配
隨便一提,由於nginx使用花括號{}判斷區塊,因此當正則中包含花括號時,則必須用雙引號將正則包起來.對下面講到的rewrite語句中的正則亦是如此.
好比 「\d{4}\d{2}\.+」
- 使用-f,-d,-e,-x檢測文件和目錄,跟~相似,前置!則爲」非」操做
-f 檢測文件存在
-d 檢測目錄存在
-e 檢測文件,目錄或者符號連接存在
-x 檢測文件可執行
舉例:
if ( $http_user_agent ~ MSIE ) { rewrite ^ (. * )$ /msie / $1 break; }
//若是UA包含」MSIE」,rewrite 請求到/msie目錄下
if ( $http_cookie ~ * "id=([^;] +)(?:;|$)" ) { set $id $1;}
//若是cookie匹配正則,設置變量$id等於正則引用部分
if ( $request_method = POST ) { return 405; }
//若是提交方法爲POST,則返回狀態405 (Method not allowed)
if ( !-f $request_filename ) { break; proxy_pass http://127.0.0.1; }
//若是請求文件名不存在,則反向代理localhost
if ( $args ~ post=140 ) { rewrite ^ http: //example.com / permanent;}
//若是query string中包含」post=140″,永久重定向到example.com
3.return 可用來直接設置HTTP返回狀態,好比403,404等(301,302不可用return返回,這個下面會在rewrite提到)
4.break 當即中止rewrite檢測,跟下面講到的rewrite的break flag功能是同樣的,區別在於前者是一個語句,後者是rewrite語句的flag
5.rewrite 最核心的功能(廢話)
其中標誌位有四種
break – 中止rewrite檢測,也就是說當含有break flag的rewrite語句被執行時,該語句就是rewrite的最終結果
last – 中止rewrite檢測,可是跟break有本質的不一樣,last的語句不必定是最終結果,這點後面會跟nginx的location匹配一塊兒提到
redirect – 返回302臨時重定向,通常用於重定向到完整的URL(包含http:部分)
permanent – 返回301永久重定向,通常用於重定向到完整的URL(包含http:部分)
由於301和302不能簡單的只單純返回狀態碼,還必須有重定向的URL,這就是return指令沒法返回301,302的緣由了. 做爲替換,rewrite能夠更靈活的使用redirect和permanent標誌實現301和302. 好比上一篇日誌中提到的Blog搬家要作的域名重定向,在nginx中就會這麼寫
rewrite ^ (.* )$ http://newdomain.com/ permanent;
舉例來講一下rewrite的實際應用
rewrite ^ (/download /. * ) /media / (. * )\.. *$ $1 /mp3 / $2.mp3 last;
若是請求爲 /download/eva/media/op1.mp3 則請求被rewrite到 /download/eva/mp3/op1.mp3
要注意的是rewrite有不少潛規則須要注意:
- rewrite的生效區塊爲sever, location, if
- rewrite只對相對路徑進行匹配,不包含hostname 好比說以上面301重定向的例子說明
rewrite ~ * cafeneko\.info http://newdomain.com / permanent;
這句是永遠沒法執行的,以這個URL爲例
http://blog.cafeneko.info/2010/10/neokoseseiki_in_new_home/?utm_source=rss&utm_medium=rss&utm_campaign=neokoseseiki_in_new_home
其中cafeneko.info叫作hostname,再日後到?爲止叫作相對路徑,?後面的一串叫作query string
對於rewrite來講,其正則表達式僅對」/2010/10/neokoseseiki_in_new_home」這一部分進行匹配,即不包含hostname,也不包含query string .因此除非相對路徑中包含跟域名同樣的string,不然是不會匹配的.
若是非要作域名匹配的話就要使用if語句了,好比進行去www跳轉
if ( $host ~ * ^www\. (cafeneko\.info) ) { set $host_without_www $1; rewrite ^ (. * )$ http: // $host_without_www $1permanent; }
- 使用相對路徑rewrite時,會根據HTTP header中的HOST跟nginx的server_name匹配後進行rewrite,若是HOST不匹配或者沒有HOST信息的話則rewrite到server_name設置的第一個域名,若是沒有設置server_name的話,會使用本機的localhost進行rewrite
- 前面提到過,rewrite的正則是不匹配query string的,因此默認狀況下,query string是自動追加到rewrite後的地址上的,若是不想自動追加query string,則在rewrite地址的末尾添加?
rewrite ^ /users/ (. * )$ /show? user= $1? last;
rewrite的基本知識就是這麼多..但尚未完..還有最頭疼的部分沒有說…
/2 Nginx location 和 rewrite retry
nginx的rewrite有個很奇特的特性 — rewrite後的url會再次進行rewrite檢查,最多重試10次,10次後尚未終止的話就會返回HTTP 500
last和break最大的不一樣在於
- break是終止當前location的rewrite檢測,並且再也不進行location匹配
– last是終止當前location的rewrite檢測,但會繼續重試location匹配並處理區塊中的rewrite規則
仍是這個該死的例子
location /download/ { rewrite ^ ( /download /. * ) /media / (. * )\.. *$ $1 /mp3 / $2.mp3 ; rewrite ^ ( /download /. * )/movie / (. * )\.. *$ $1 /avi / $2.mp3 ; rewrite ^ ( /download /. * ) /avvvv / (. * )\.. *$ $1 /rmvb / $2.mp3 ; }
上面沒有寫標誌位,請各位自行腦補…
若是請求爲 /download/acg/moive/UBW.avi
last的狀況是: 在第2行rewrite處終止,並重試location /download..死循環
break的狀況是: 在第2行rewrite處終止,其結果爲最終的rewrite地址.
也就是說,上面的某位試圖下載eva op不但沒下到反而被HTTP 500射了一臉的例子正是由於用了last標誌因此纔會形成死循環,若是用break就沒事了.
location /download/ { rewrite ^ ( /download /. * ) /media / (. * )\.. *$ $1 /mp3 / $2.mp3 break; }
對於這個問題,我我的的建議是,若是是全局性質的rewrite,最好放在server區塊中並減小沒必要要的location區塊.location區塊中的rewrite要想清楚是用last仍是break.
有些狀況是要用last的. 典型的例子就是wordpress的permalink rewrite
常見的狀況下, wordpress的rewrite是放在location /下面,並將請求rewrite到/index.php
這時若是這裏使用break乃就掛了,不信試試. b( ̄▽ ̄)d…由於nginx返回的是沒有解釋的index.php的源碼…
這裏必定要使用last才能夠在結束location / 的rewrite, 並再次命中location ~ \.php$,將其交給fastcgi進行解釋.其後返回給瀏覽器的纔是解釋過的html代碼.
關於nginx rewrite的簡介到這裏就所有講完了,水平及其有限,請你們指出錯漏…
結合QeePHP的例子
if (!-d $request_filename) { rewrite ^/([a-z-A-Z]+)/([a-z-A-Z]+)/?(.*)$ /index.php?namespace=user&controller=$1&action=$2&$3 last; rewrite ^/([a-z-A-Z]+)/?$ /index.php?namespace=user&controller=$1 last; break; }
多目錄轉成參數
abc.domian.com/sort/2 => abc.domian.com/index.php?act=sort&name=abc&id=2
if ($host ~* (.*)\.domain\.com) { set $sub_name $1; rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last; }
目錄對換
/123456/xxxx -> /xxxx?id=123456
rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;
例以下面設定nginx在用戶使用ie的使用重定向到/nginx-ie目錄下:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; }
目錄自動加「/」
if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; }
禁止htaccess
location ~/\.ht { deny all; }
禁止多個目錄
location ~ ^/(cron|templates)/ { deny all; break; }
禁止以/data開頭的文件
能夠禁止/data/下多級目錄下.log.txt等請求;
location ~ ^/data { deny all; }
禁止單個目錄
不能禁止.log.txt能請求
location /searchword/cron/ { deny all; }
禁止單個文件
location ~ /data/sql/data.sql { deny all; }
給favicon.ico和robots.txt設置過時時間;
這裏爲favicon.ico爲99天,robots.txt爲7天並不記錄404錯誤日誌
location ~(favicon.ico) { log_not_found off; expires 99d; break; } location ~(robots.txt) { log_not_found off; expires 7d; break; }
設定某個文件的過時時間;這裏爲600秒,並不記錄訪問日誌
location ^~ /html/scripts/loadhead_1.js { access_log off; root /opt/lampp/htdocs/web; expires 600; break; }
文件反盜鏈並設置過時時間
這裏的return 412 爲自定義的http狀態碼,默認爲403,方便找出正確的盜鏈的請求
「rewrite ^/ http://leech.divmy.com/leech.gif;」顯示一張防盜鏈圖片
「access_log off;」不記錄訪問日誌,減輕壓力
「expires 3d」全部文件3天的瀏覽器緩存
location ~* ^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ { valid_referers none blocked *.c1gstudio.com *.c1gstudio.net localhost 208.97.167.194; if ($invalid_referer) { rewrite ^/ http://leech.divmy.com/leech.gif; return 412; break; } access_log off; root /opt/lampp/htdocs/web; expires 3d; break; }
只充許固定ip訪問網站,並加上密碼
root /opt/htdocs/www; allow 208.97.167.194; allow 222.33.1.2; allow 231.152.49.4; deny all; auth_basic 「C1G_ADMIN」; auth_basic_user_file htpasswd;
將多級目錄下的文件轉成一個文件,加強seo效果
/job-123-456-789.html 指向/job/123/456/789.html
rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last;
將根目錄下某個文件夾指向2級目錄
如/shanghaijob/ 指向 /area/shanghai/
若是你將last改爲permanent,那麼瀏覽器地址欄顯是/location/shanghai/
rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;
上面例子有個問題是訪問/shanghai 時將不會匹配
rewrite ^/([0-9a-z]+)job$ /area/$1/ last; rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;
這樣/shanghai 也能夠訪問了,但頁面中的相對連接沒法使用,
如./list_1.html真實地址是/area/shanghia/list_1.html會變成/list_1.html,導至沒法訪問。
那我加上自動跳轉也是不行咯
(-d $request_filename)它有個條件是必需爲真實目錄,而個人rewrite不是的,因此沒有效果
if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; }
知道緣由後就好辦了,讓我手動跳轉吧
rewrite ^/([0-9a-z]+)job$ /$1job/ permanent; rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;
文件和目錄不存在的時候重定向:
if (!-e $request_filename) { proxy_pass http://127.0.0.1; }
域名跳轉
server { listen 80; server_name jump.88dgw.com; index index.html index.htm index.php; root /opt/lampp/htdocs/www; rewrite ^/ http://www.88dgw.com/; access_log off; }
多域名轉向
server_name www.7oom.com/ www.divmy.com/; index index.html index.htm index.php; root /opt/lampp/htdocs; if ($host ~ 「c1gstudio\.net」) { rewrite ^(.*) http://www.7oom.com$1/ permanent; }
三級域名跳轉
if ($http_host ~* 「^(.*)\.i\.c1gstudio\.com$」) { rewrite ^(.*) http://top.88dgw.com$1/; break; }
域名鏡向
server { listen 80; server_name mirror.c1gstudio.com; index index.html index.htm index.php; root /opt/lampp/htdocs/www; rewrite ^/(.*) http://www.divmy.com/$1 last; access_log off; }
某個子目錄做鏡向
location ^~ /zhaopinhui { rewrite ^.+ http://zph.divmy.com/ last; break; }
discuz ucenter home (uchome) rewrite
rewrite ^/(space|network)-(.+)\.html$ /$1.php?rewrite=$2 last; rewrite ^/(space|network)\.html$ /$1.php last; rewrite ^/([0-9]+)$ /space.php?uid=$1 last;
discuz 7 rewrite
rewrite ^(.*)/archiver/((fid|tid)-[\w\-]+\.html)$ $1/archiver/index.php?$2 last; rewrite ^(.*)/forum-([0-9]+)-([0-9]+)\.html$ $1/forumdisplay.php?fid=$2&page=$3 last; rewrite ^(.*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/viewthread.php?tid=$2&extra=page\%3D$4&page=$3 last; rewrite ^(.*)/profile-(username|uid)-(.+)\.html$ $1/viewpro.php?$2=$3 last; rewrite ^(.*)/space-(username|uid)-(.+)\.html$ $1/space.php?$2=$3 last; rewrite ^(.*)/tag-(.+)\.html$ $1/tag.php?name=$2 last;
給discuz某版塊單獨配置域名
server_name bbs.c1gstudio.com news.c1gstudio.com; location = / { if ($http_host ~ news\.divmy.com$) { rewrite ^.+ http://news.divmy.com/forum-831-1.html last; break; } }
discuz ucenter 頭像 rewrite 優化
location ^~ /ucenter { location ~ .*\.php?$ { #fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fcgi.conf; } location /ucenter/data/avatar { log_not_found off; access_log off; location ~ /(.*)_big\.jpg$ { error_page 404 /ucenter/p_w_picpaths/noavatar_big.gif; } location ~ /(.*)_middle\.jpg$ { error_page 404 /ucenter/p_w_picpaths/noavatar_middle.gif; } location ~ /(.*)_small\.jpg$ { error_page 404 /ucenter/p_w_picpaths/noavatar_small.gif; } expires 300; break; } }
jspace rewrite
location ~ .*\.php?$ { #fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fcgi.conf; } location ~* ^/index.php/ { rewrite ^/index.php/(.*) /index.php?$1 break; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fcgi.conf; }
另外這裏還有一個工具能夠直接把apache規則轉化爲nginx規則
http://www.anilcetin.com/convert-apache-htaccess-to-nginx/
參考:
http://wiki.nginx.org/NginxChsHttpRewriteModule
http://blog.csdn.net/cnbird2008/archive/2009/08/04/4409620.aspx
http://www.divmy.com/