Apache的URL地址重寫
http://hi.baidu.com/sonan/blog/item/c408963d89468208bba16716.html
第一種方法:Apache環境中如果要將URL地址重寫,正則表達式是最基本的要求,但對於一般的URL地址來說,基本的匹配就能實現我們大部分要求,因此除非 是非常特殊的URL地址,但這不是我要討論的範圍,簡單幾招學會Apache中URL地址重寫,通過實例展示,輕鬆學會URL地址重寫:
URL實例
重寫URL:http://www.baidu.com/?p=152
原始URL:http://www.baidu.com/p152.html
重寫規則:
^p([0-9]+)\.html /?p=$1 [L]
正則基礎知識:
^ 匹配行的開始,匹配URL地址的開頭部分,對於RewriteRule而言,域名(http://www.biuuu.com)不是URL地址的一部分,如上:?p=152
() 分隔一個被捕獲的表達式,如上:([0-9]+)
[] 定義字符類,如上:[0-9] 表示從0-9的數字
+ 說明前面的字符可以被重複匹配1次或數次,如上:[0-9]+,表示任何數字組合
\ 字符轉義,如上:轉義.
其它:
[L] 表示last,停止匹配其它
方法如下:
1,打開httpd.conf文件,找到
#LoadModule rewrite_module modules/mod_rewrite.so 註釋前面#
2,打開httpd-vhosts.conf文件,在VirtualHost添加重寫規則,
RewriteEngine On
RewriteRule ^p([0-9]+)\.html /?p=$1 [L]
基本上就上面這兩個步驟,其實總的來說,Apache中URL地址重寫還是比較簡單的,比看文檔學習要快的多,不過要想深入瞭解還是有必要看看相關文檔的,其它規則可以自定義。記住一點:任何匹配其實就是一個正則表達式的替換過程。
創建友好的搜索引擎URL地址對於PHP程序員來說非常重要,因此簡單學會Apache中URL地址重寫將是一項最基本的要求。
第二種方法:
1,首先檢查是否已安裝rewrite模塊:
cat httpd.conf | grep rewrite
LoadModule rewrite_module modules/mod_rewrite.so
2,生成僞靜態html連接:
(1)生成僞靜態html
在<VirtualHost>段最後加入
RewriteEngine on
RewriteRule /goods([0-9]+).html /goods.php?id=$1 [PT]
更標準的寫法爲:
RewriteRule ^(.*)/goods([0-9]+).html$ $1/goods.php?id=$2 [PT]
更簡潔的寫法:
/goods(\d+)\.html /goods\.php\?id=$1
第一個(0-9]+)對應參數$1,以此類推第二個對應$2
舉例:
RewriteRule /forum-([0-9]+)-([0-9]+)\.html /forumdisplay.php?fid=$1&page=$2 [PT]
測試http://www.xxx.com/goods1.html 是否與/goods.php?id=1的內容相同
最後將所有鏈接換成設置後的僞靜態html地址方式
[PT]:url全局轉換,即轉換過的goods31.html對應goods.php?id=31 (默認就是這個不加參數)
[R]: url重定向 即使用goods31.html訪問時跳轉到goods.php?id=31
3,防盜鏈:
RewriteCrond %{HTTP_HOST} !upkiller.com [R=301,L]
RewriteRule ^(.*)$ http://www.upkiller.com/warning.html [R=301,L]
把不是來自upkiller.com的請求重定向到http://www.upkiller.com
更好的做法:
RewriteCond %{HTTP_REFERER} !^http://(www\.)?upkiller\.com/.*$ [NC]
RewriteRule \.(mp3|rar|jpe|gif)$ http://www.upkiller.com/warning.jpg [R=301,L]
4,防百度爬蟲:
RewriteCond %{HTTP_USER_AGENT} ^Baiduspider [OR]
RewriteRule ^(.*)$ http://www.google.com [R=301,L]
把來自百度的爬蟲轉到goole
PS:PHP僞靜態方式
方法一:
比如這個網頁
http://www.xxxx.com/soft.php/1,100,8630.html
其實處理的腳本是soft.php 參數爲1,100,8630
相當於soft.php?a=1&b=1=100&c=8630 只不過這樣的URL太難記。搜索引擎也不喜歡。
真靜態只是完全生成了HTML。
客戶端訪問的時候直接輸出。不用腳本解釋。在流量非常大的時候(比如每天有上百萬的訪問量的時候)會起到很好的效果。也就是說服務器端實實在在的存在這個HTML頁面。
當然在你網站的流量沒有那麼大的時候。URL重寫是最好的方法(個人觀點,大流量的時候可以考慮負載均衡了。同樣沒有關係)
附URL重寫的方法有很多種,APACHE,IISREWRITE。甚至PHP腳本都可以直接處理。比如上例中就是PHP腳本直接處理(該方法好處是大流量的時候直接減輕WEB伺服器的壓力。PS:同樣也是個人觀點:
================================================
下面以程序爲例講一下PHP僞靜態的程序實現方法,其實這方法我之前已經有在其它論壇社區發過
程序爲例:
http://www.xxxx.com/soft.php/1,100,8630.html
CODE:
//利用server變量 取得PATH_INFO信息 該例中爲 /1,100,8630.html 也就是執行腳本名後面的部分
if(@$path_info =$_SERVER["PATH_INFO"]){
//正則匹配一下參數
if(preg_match("/\/(\d+),(\d+),(\d+)\.html/si",$path_info,$arr_path)){
$gid =intval($arr_path[1]); //取得值 1
$sid =intval($arr_path[2]); //取得值100
$softid =intval($arr_path[3]); //取得值8630
}else die("Path:Error!");
//相當於soft.php?gid=1&sid=100&softid=8630
//就是這麼簡單了。~)
方法二:
一 打開 Apache 的配置文件 httpd.conf 。
二 將#LoadModule rewrite_module modules/mod_rewrite前面的#去掉
三 在 httpd.conf中添加:
<IfModule mod_rewrite.c>
RewriteEngine On
#RewriteCond %{ENV:SCRIPT_URL} (?:index|dispbbs)[-0-9]+.html
RewriteRule ^(.*?(?:index|dispbbs))-([-0-9]+).html 1.php?__is_apache_rewrite=1&__rewrite_arg=2
</IfModule>
四 要實現asp帖子URL到php帖子的映射,在 第三步的<IfModule mod_rewrite.c>和</IfModule>之間添加:
RewriteMap tolowercase int:tolower
RewriteCond %{QUERY_STRING} (?:boardid|page|id|replyid|star|skin)=d+ [NC]
RewriteRule ^(.*(?:index|dispbbs)).asp 1.php?{tolowercase:%{QUERY_STRING}}&__is_apache_rewrite=1
五 保存httpd.conf並重啓Apache
方法三:
<?php
/*
功能:PHP僞靜態化頁面的實現
具體用法:
例如鏈接爲:test.php/year/2006/action/_add.html
mod_rewrite();
$yearn=$_GET["year"];//結果爲'2006'
$action=$_GET["action"];//結果爲'_add'
*/
function mod_rewrite(){
global $_GET;
$nav=$_SERVER["REQUEST_URI"];
$script_name=$_SERVER["SCRIPT_NAME"];
$nav=substr(ereg_replace("^$script_name","",urldecode($nav)),1);
$nav=preg_replace("/^.ht(m){1}(l){0,1}$/","",$nav);//這句是去掉尾部的.html或.htm
$vars = explode("/",$nav);
for($i=0;$i<Count($vars);$i+=2){
$_GET["$vars[$i]"]=$vars[$i+1];
}
return $_GET;
}
mod_rewrite();
$yearn=$_GET["year"];//結果爲'2006'
$action=$_GET["action"];//結果爲'_add'
echo $yearn;
echo $action;
?>
<?php
/*
功能:PHP僞靜態化頁面的實現
具體用法:
例如鏈接爲:test.php/year/2006/action/_add.html
mod_rewrite();
$yearn=$_GET["year"];//結果爲'2006'
$action=$_GET["action"];//結果爲'_add'
*/
function mod_rewrite(){
global $_GET;
$nav=$_SERVER["REQUEST_URI"];
$script_name=$_SERVER["SCRIPT_NAME"];
$nav=substr(ereg_replace("^$script_name","",urldecode($nav)),1);
$nav=preg_replace("/^.ht(m){1}(l){0,1}$/","",$nav);//這句是去掉尾部的.html或.htm
$vars = explode("/",$nav);
for($i=0;$i<Count($vars);$i+=2){
$_GET["$vars[$i]"]=$vars[$i+1];
}
return $_GET;
}
mod_rewrite();
$yearn=$_GET["year"];//結果爲'2006'
$action=$_GET["action"];//結果爲'_add'
echo $yearn;
echo $action;
=====================================================================================================================
Apache的Mod_rewrite學習 (RewriteCond重寫規則的條件)
RewriteCond Syntax: RewriteCond TestString CondPattern [flags] RewriteCond指令定義一條規則條件。在一條RewriteRule指令前面可能會有一條或多條RewriteCond指令,只有當自身的模 板(pattern)匹配成功且這些條件也滿足時規則才被應用於當前URL處理。 TestString是一個字符串,除了包含普通的字符外,還可以包括下列的可擴展結構:
1. $N,RewriteRule後向引用,其中(0 <= N <= 9) $N引用緊跟在RewriteCond後面的RewriteRule中模板中的括號中的模板在當前URL中匹配的數據。
2. %N,RewriteCond後向引用,其中(0 <= N <= 9) %N引用最後一個RewriteCond的模板中的括號中的模板在當前URL中匹配的數據。
3. ${mapname:key|default},RewriteMap擴展. 具體參見RewriteMap
4. %{ NAME_OF_VARIABLE } ,服務器變量。 變量的名字如下表(分類顯示)
5.
6. 特別說明:
o SCRIPT_FILENAME和REQUEST_FILENAME變量含有相同的值,也就是Apache服務器內部數據結構request_rec的 filename字段的值。第一個變量是一個CGI變量,而第二個則與REQUEST_URI(含有request_rec數據結構中uri字段的值)保 持一致。
o %{ENV:variable}中的variable可以是任何環境變量的名字。對其值的查找,先通過Apache內部的數據結構,(如找不到)再在Apache服務器進程中通過getenv()查找。
o %{HTTP:header}中的header可以是任何HTTP MIME-header的名字,其值通過查找HTTP請求信息而得。
o %{LA-U:variable} 用來引用後續API階段中定義的、當前還不知道的值,具體實現是通過執行一個基於URL的內部的sub-request來決定的variable的最終的 值。例如,假如你想在服務器範圍內利用REMOTE_USER的值來完成重寫,但這個值是在驗證階段設置的,而驗證階段是在URL轉換階段的後面。從另一 方面講,由於mod_rewrite在修補(fixup)API階段進行目錄範圍的重寫,而修補階段在驗證階段的後面,所以此時只要用% {REMOTE_USER}就可以取得該值了。
o %{LA-F:variable},執行一個基於文件名字(filename)的內部sub-request來決定variable的最終的值。大多數時間內,這和LA-U相同。
CondPattern是一個條件模板,也就是說,是一個擴展正則式(extended regular expression),用與跟TestString進行匹配。作爲一個標準的擴展正則式,CondPattern有以下補充:
1. 可以在模板串前增加一個!前綴,以用表示不匹配模板。但並不是所有的test都可以加!前綴。
2. CondPattern中可以使用以下特殊變量:
o '<CONDPATTERN' (小於,基於字母順序) 將condPattern當作一個普通字符串,將它和TestString進行比較,當TestString 的字符小於CondPattern爲真.
o '>CondPattern' (大於) 將condPattern當作一個普通字符串,將它和TestString進行比較,當TestString 的字符大於CondPattern爲真.
o '=CondPattern' (等於) 將condPattern當作一個普通字符串,將它和TestString進行比較,當TestString 與CondPattern完全相同時爲真.如果CondPattern只是 "" (兩個引號緊挨在一起) 此時需TestString 爲空字符串方爲真.
o '-d' (是否爲目錄) 將testString當作一個目錄名,檢查它是否存在以及是否是一個目錄.
o '-f' (是否是regular file) 將testString當作一個文件名,檢查它是否存在以及是否是一個regular文件.
o '-s' (是否爲長度不爲0的regular文件) 將testString當作一個文件名,檢查它是否存在以及是否是一個長度大於0的regular文件
o '-l' (是否爲symbolic link) 將testString當作一個文件名,檢查它是否存在以及是否是一個 symbolic link.
o '-F' (通過subrequest來檢查某文件是否可訪問) 檢查TestString是否是一個合法的文件,而且通過服務器範圍內的當前設置的訪問控制進行訪問。這個檢查是通過一個內部subrequest完成 的, 因此需要小心使用這個功能以降低服務器的性能。
o '-U' (通過subrequest來檢查某個URL是否存在) 檢查TestString是否是一個合法的URL,而且通過服務器範圍內的當前設置的訪問控制進行訪問。這個檢查是通過一個內部subrequest完成 的, 因此需要小心使用這個功能以降低服務器的性能。
[flags]是第三個參數,多個標誌之間用逗號分隔。
1. 'nocase|NC' (不區分大小寫) 在擴展後的TestString和CondPattern中,比較時不區分文本的大小寫。注意,這個標誌對文件系統和subrequest檢查沒有影響.
2. 'ornext|OR' (建立與下一個條件的或的關係) 默認的情況下,二個條件之間是AND的關係,用這個標誌將關係改爲OR。例如: RewriteCond %{REMOTE_HOST} ^host1.* [OR] RewriteCond %{REMOTE_HOST} ^host2.* [OR] RewriteCond %{REMOTE_HOST} ^host3.* RewriteRule ... 如果沒有[OR]標誌,需要寫三個條件/規則.
例子:根據客戶端瀏覽器的不同,返回不同的首頁面。 RewriteCond %{HTTP_USER_AGENT} ^Mozilla.* RewriteRule ^/$ /homepage.max.html [L] RewriteCond %{HTTP_USER_AGENT} ^Lynx.* RewriteRule ^/$ /homepage.min.html [L] RewriteRule ^/$ /homepage.std.html [L]
當你在地址欄裏輸入 sina.com.cn google.cn
看看有什麼變化?是不是會自動跳轉到 www.sina.com.cn www.google.cn
這一技術通過apache的rewrite可以實現,當然你得把 不帶www的域名指向你服務器的IP
要是虛擬主機的話,得在viralhost段加入 ServerAlias xxx.com
然後打開重寫引擎功能
RewriteEngine On
能過rewritecond判斷主機名是否帶www
RewriteCond %{HTTP_HOST} ^xxx\.com$ [NC]
然後來一條
RewriteRule ^/(.*)$ http://www.xxx.com/$1 [R=301,L]
OK,重起apache,現在在瀏覽器中輸入 xxx.com 看看是不是自動變成了 www.xxx.com 了呢。
重新整理一下就是:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^xxx\.com$ [NC]
RewriteRule ^/(.*)$ http://www.xxx.com/$1 [R=301,L]
源地址: http://blog.csdn.net/keyunq/archive/2008/06/11/2536875.aspx
一 .RewriteRule
Syntax: RewriteRule Pattern Substitution [flags]
一條RewriteRule指令,定義一條重寫規則,規則間的順序 非常重要。對Apache1.2及以後的版本,模板(pattern)是一個POSIX正則式,用以匹配當前的URL。當前的URL不一定是用記最初提交 的URL,因爲可能用一些規則在此規則前已經對URL進行了處理。
對mod_rewrite來說,!是個合法的模板前綴,表示“非”的意思,這對描述“不滿足某種匹配條件”的情況非常方便,或用作最後一條默認規則。當使用!時,不能在模板中有分組的通配符,也不能做後向引用。
當匹配成功後,Substitution會被用來替換相應的匹配,它除了可以是普通的字符串以外,還可以包括:
1. $N,引用RewriteRule模板中匹配的 相關 字串,N表示序號,N=0..9
2. %N,引用最後一個RewriteCond模板中匹配的數據,N表示序號
3. %{VARNAME},服務器變量
4. ${mapname:key|default},映射函數調用
這些特殊內容的擴展,按上述順序進行。
一個URL的全部相關部分都會被Substitution替換,而且這個替換過程會一直持續到所有的規則都被執行完,除非明確地用L標誌中斷處理過程。
當susbstitution有”-”前綴時,表示不進行替換,只做匹配檢查。
利用RewriteRule,可定義含有請求串(Query String)的URL,此時只需在Sustitution中加入一個?,表示此後的內容放入QUERY_STRING變量中。如果要清空一個 QUERY_STRING變量,只需要以?結束Substitution串即可。
如果給一個Substitution增加一個
1. 'redirect|R [=code]' (強制重定向)
給當前的URI增加前綴
2. 'forbidden|F' (強制禁止訪問URL所指的資源)
立即返回狀態值403 (FORBIDDEN)的應答包。將這個標誌與合適的RewriteConds 聯合使用,可以阻斷訪問某些URL。
3. 'gone|G' (強制返回URL所指資源爲不存在(gone))
立即返回狀態值410 (GONE)的應答包。用這個標誌來標記URL所指的資源永久消失了.
4. # 'proxy|P' (強制將當前URL送往代理模塊(proxy module))
這個標誌,強制將substitution當作一個發向代理模塊的請求,並立即將共送往代理模塊。因此,必須確保substitution串是一個合法的URI (如, 典型的情況是以
5. 'last|L' (最後一條規則)
中止重寫流程,不再對當前URL施加更多的重寫規則。這相當於perl的last命令或C的break命令。
6. 'next|N' (下一輪)
重新從第一條重寫規則開始執行重寫過程,新開的過程中的URL不應當與最初的URL相同。 這相當於Perl的next命令或C的continue命令. 千萬小心不要產生死循環。
7. # 'chain|C' (將當前的規則與其後續規則綑綁(chained))
當規則匹配時,處理過程與沒有綑綁一樣;如果規則不匹配,則綑綁在一起的後續規則也不在檢查和執行。
8. 'type|T=MIME-type' (強制MIME類型)
強制將目標文件的MIME-type爲某MIME類型。例如,這可用來模仿mod_alias模塊對某目錄的ScriptAlias指定,通過強制將該目錄下的所有文件的類型改爲 “application/x-httpd-cgi”.
9. 'nosubreq|NS' (used only if no internal sub-request )
這個標誌強制重寫引擎跳過爲內部sub-request的重寫規則.例如,當mod_include試圖找到某一目錄下的默認文件時 (index.xxx),sub-requests 會在Apache內部發生. Sub-requests並非總是有用的,在某些情況下如果整個規則集施加到它上面,會產生錯誤。利用這個標誌可排除執行一些規則。
10. 'nocase|NC' (模板不區分大小寫)
這個標誌會使得模板匹配當前URL時忽略大小寫的差別。
11. 'qsappend|QSA' (追加請求串(query string))
這個標誌,強制重寫引擎爲Substitution的請求串追加一部分串,則不是替換掉原來的。藉助這個標誌,可以使用一個重寫規則給請求串增加更多的數據。
12. 'noescape|NE' (不對輸出結果中的特殊字符進行轉義處理)
通常情況下,mod_write的輸出結果中,特殊字符(如'%', '$', ';', 等)會轉義爲它們的16進制形式(如分別爲'%25', '%24', and '%3B')。這個標誌會禁止mod_rewrite對輸出結果進行此類操作。 這個標誌只能在 Apache 1.3.20及以後的版本中使用。
13. 'passthrough|PT' (通過下一個處理器)
這個標誌強制重寫引擎用filename字段的值來替換內部request_rec數據結構中uri字段的值。. 使用這個標誌,可以使後續的其它URI-to-filename轉換器的Alias、ScriptAlias、Redirect等指令,也能正常處理 RewriteRule指令的輸出結果。用一個小例子來說明它的語義:如果要用mod_rewrite的重寫引擎將/abc轉換爲/def,然後用 mod_alas將/def重寫爲ghi,則要:
RewriteRule ^/abc(.*) /def$1 [PT]
Alias /def /ghi
如 果PT標誌被忽略,則mod_rewrite也能很好完成工作,如果., 將 uri=/abc/... 轉換爲filename=/def/... ,完全符合一個URI-to-filename轉換器的動作。接下來 mod_alias 試圖做 URI-to-filename 轉換時就會出問題。
注意:如果要混合都含有URL-to-filename轉換器的不同的模塊的指令,必須用這個標誌。最典型的例子是mod_alias和mod_rewrite的使用。
14. 'skip|S=num' (跳過後面的num個規則)
當前規則匹配時,強制重寫引擎跳過後續的num個規則。用這個可以來模仿if-then-else結構:then子句的最後一條rule的標誌是skip=N,而N是else子句的規則條數。
15. 'env|E=VAR:VAL' (設置環境變量)
設置名爲VAR的環境變量的值爲VAL,其中VAL中可以含有正則式的後向引用($N或%N)。這個標誌可以使用多次,以設置多個環境變量。這兒設置的 變量,可以在多種情況下被引用,如在XSSI或CGI中。另外,也可以在RewriteCond模板中以%{ENV:VAR}的形式被引用。
16.
注意:一定不要忘記,在服務器範圍內的配置文件中,模板(pattern)用以匹配整個URL;而在目錄範圍內的配置文件中,目錄前綴總是被自動去掉後再 進行模板匹配的,且在替換完成後自動再加上這個前綴。這個功能對很多種類的重寫是非常重要的,因爲如果沒有去前綴,則要進行父目錄的匹配,而父目錄的信息 並不是總能得到的。一個例外是,當substitution中有http://打頭時,則不再自動增加前綴了,如果P標誌出現,則會強制轉向代理。
注 意:如果要在某個目錄範圍內啓動重寫引擎,則需要在相應的目錄配置文件中設置“RewriteEngine on”,且目錄的“Options FollowSymLinks”必須設置。如果管理員由於安全原因沒有打開FollowSymLinks,則不能使用重寫引擎。
http://hostname 開頭),否則會從代理模塊得到一個錯誤. 這個標誌,是ProxyPass指令的一個更強勁的實現,將遠程請求(remote stuff)映射到本地服務器的名字空間(namespace)中來。
注意,使用這個功能必須確保代理模塊已經編譯到Apache 服務器程序中了. 可以用“httpd -l ”命令,來檢查輸出中是否含有mod_proxy.c來確認一下。如果沒有,而又需要使用這個功能,則需要重新編譯``httpd''程序並使用 mod_proxy有效。 http://thishost[:thisport]/ , 從而生成一個新的URL,強制生成一個外部重定向(external redirection,指生的URL發送到客戶端,由客戶端再次以新的URL發出請求,雖然新URL仍指向當前的服務器). 如果沒有指定的code值,則HTTP應答以狀態值302 (MOVED TEMPORARILY),如果想使用300-400(不含400)間的其它值可以通過在code的位置以相應的數字指定,也可以用標誌名指定: temp (默認值), permanent, seeother.
注意,當使用這個標誌時,要確實substitution是個合法的URL,這個標誌只是在URL前增加http://thishost[:thisport]/ 前綴而已,重寫操作會繼續進行。如果要立即將新URL重定向,用L標誌來中重寫流程。http://thishost[:port ]的前綴,則mod_rewrite會自動將此前綴去掉。因此,利用 http://thisthost 做一個無條件的重定向到自己,將難以奏效。要實現這種效果,必須使用R標誌。
Flags是可選參數,當有多個標誌同時出現時,彼此間以逗號分隔。