Published onDecember 26, 2011in Linux. 0 Comments Tags: apache, ngnix, rewrite.php
最近在VPS上嘗試配置安裝一個網站,VPS安裝了LNMP(Linux+Nginx+MySQL+php)在配置重定規則的時候常常遇到一些問題,直接用Apache的規則到Nginx下沒起做用。原來Apache 重寫的規則到nginx上還有一些不太同樣的地方。css
這裏只是簡單記錄一些學習示例,高手略過,新手能夠看一下。 html
Nginx Rewrite規則相關指令
Nginx Rewrite規則相關指令有if、rewrite、set、return、break等,其中rewrite是最關鍵的指令。一個簡單的Nginx Rewrite規則語法以下:linux
rewrite ^/b/(.*)\.html /play.php?video=$1 break;nginx
若是加上if語句,示例以下:web
if (!-f $request_filename)sql
rewrite ^/img/(.*)$ /site/$host/images/$1 last;express
Nginx與Apache的Rewrite規則實例對比 apache
簡單的Nginx和Apache 重寫規則區別不大,基本上可以徹底兼容。例如:瀏覽器
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 規則:
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的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=/p>
Nginx Rewrite 規則:
rewrite ^/user/login/$ /user/login.php?login=1&forward=/p>
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 regex replacement flag
默認: none
做用域: server, location, if
This directive changes URI in accordance with the regular expression and the replacement string. Directives are carried out in order of appearance in the configuration file.
這個指令根據表達式來更改URI,或者修改字符串。指令根據配置文件中的順序來執行。
Be aware that the rewrite regex only matches the relative path instead of the absolute URL. If you want to match the hostname, you should use an if condition, like so:
注意重寫表達式只對相對路徑有效。若是你想配對主機名,你應該使用if語句。
rewrite只是會改寫路徑部分的東東,不會改動用戶的輸入參數,所以這裏的if規則裏面,你無需關心用戶在瀏覽器裏輸入的參數,rewrite後會自動添加的,所以,咱們只是加上了一個?號和後面咱們想要的一個小小的參數 ***https=1就能夠了。
nginx的rewrite規則參考:
~ 爲區分大小寫匹配
~* 爲不區分大小寫匹配
!~和!~*分別爲區分大小寫不匹配及不區分大小寫不匹
-f和!-f用來判斷是否存在文件
-d和!-d用來判斷是否存在目錄
-e和!-e用來判斷是否存在文件或目錄
-x和!-x用來判斷文件是否可執行
last 至關於Apache裏的[L]標記,表示完成rewrite,呵呵這應該是最經常使用的
break 終止匹配, 再也不匹配後面的規則
redirect 返回302臨時重定向 地址欄會顯示跳轉後的地址
permanent 返回301永久重定向 地址欄會顯示跳轉後的地址
$args
$content_length
$content_type
$document_root
$document_uri
$host
$http_user_agent
$http_cookie
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri
結合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/images/noavatar_big.gif;
}
location ~ /(.*)_middle\.jpg$ {
error_page 404 /ucenter/images/noavatar_middle.gif;
}
location ~ /(.*)_small\.jpg$ {
error_page 404 /ucenter/images/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