Terry.Li-彬

          虛其心,可解天下之問;專其心,可治天下之學(xué);靜其心,可悟天下之理;恒其心,可成天下之業(yè)。

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            143 隨筆 :: 344 文章 :: 130 評論 :: 0 Trackbacks

          Apache模塊 mod_rewrite

          說明 一個基于一定規(guī)則的實時重寫URL請求的引擎
          狀態(tài) 擴(kuò)展(E)
          模塊名 rewrite_module
          源文件 mod_rewrite.c
          兼容性 僅在 Apache 1.3 及以后的版本中可用

          概述

          此模塊提供了一個基于正則表達(dá)式分析器的重寫引擎來實時重寫URL請求。它支持每個完整規(guī)則可以擁有不限數(shù)量的子規(guī)則以及附加條件規(guī)則 的靈活而且強(qiáng)大的URL操作機(jī)制。此URL操作可以依賴于各種測試,比如服務(wù)器變量、環(huán)境變量、HTTP頭、時間標(biāo)記,甚至各種格式的用于匹配URL組成 部分的查找數(shù)據(jù)庫。

          此模塊可以操作URL的所有部分(包括路徑信息部分),在服務(wù)器級的(httpd.conf)和目錄級的(.htaccess)配置都有效,還可以生成最終請求字符串。此重寫操作的結(jié)果可以是內(nèi)部子處理,也可以是外部請求的轉(zhuǎn)向,甚至還可以是內(nèi)部代理處理。

          但是,所有這些功能和靈活性帶來一個問題,那就是復(fù)雜性,因此,不要指望一天之內(nèi)就能看懂整個模塊。

          更多的討論、細(xì)節(jié)、示例,請查看詳細(xì)的URL重寫文檔

          特殊字符的引用

          在Apache 1.3.20中,TestStringSubstitution中的特殊字符可以用前導(dǎo)斜杠(\)來實現(xiàn)轉(zhuǎn)義(即忽略其特殊含義而視之為普通字符)。 比如,Substitution可以用"\$"來包含一個美元符號,以避免mod_rewrite把它視為反向引用。

          環(huán)境變量

          此模塊會跟蹤兩個額外的(非標(biāo)準(zhǔn))CGI/SSI環(huán)境變量,SCRIPT_URLSCRIPT_URI。他們包含了當(dāng)前資源的邏輯網(wǎng)絡(luò)視圖,而標(biāo)準(zhǔn)CGI/SSI變量SCRIPT_NAMESCRIPT_FILENAME包含的是物理系統(tǒng)視圖。

          注意:這些變量保持的是其最初被請求時的URI/URL,即在任何重寫操作之前的URI/URL。其重要性在于他們是重寫操作重寫URL到物理路徑名的原始依據(jù)。

          示例

          SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html
          SCRIPT_FILENAME=/u/rse/.www/index.html
          SCRIPT_URL=/u/rse/
          SCRIPT_URI=http://en1.engelschall.com/u/rse/

          實用方案

          我們提供了URL重寫指南高級URL重寫指南文檔,列舉了許多基于URL的問題的實用方案,其中你可以找到真實有用的規(guī)則集。

          RewriteBase 指令

          說明 設(shè)置目錄級重寫的基準(zhǔn)URL
          語法 RewriteBase URL-path
          默認(rèn)值 參見使用方法
          作用域 directory, .htaccess
          覆蓋項 FileInfo
          狀態(tài) 擴(kuò)展(E)
          模塊 mod_rewrite

          RewriteBase指令顯式地設(shè)置了目錄級重寫的基準(zhǔn)URL。在下文中,你將看到RewriteBasephysical-directory-path"。

          在對一個新的URL進(jìn)行替換時,此模塊必須把這個URL重新注入到服務(wù)器處理中。為此,它必須知道其對應(yīng)的URL前綴或者說URL基準(zhǔn)。通常,此前綴就是對應(yīng)的文件路徑。但是,大多數(shù)網(wǎng)站URL不是直接對應(yīng)于其物理文件路徑的,因而一般不能做這樣的假定! 所以在這種情況下,就必須用RewriteBase指令來指定正確的URL前綴。

          例如,目錄級配置文件內(nèi)容如下:

          # /abc/def/.htaccess -- /abc/def 目錄的配置文件
          # 注意:/abc/def 是 /xyz 的物理路徑(例如存在一條'Alias /xyz /abc/def'指令)。

          RewriteEngine On

          # 讓服務(wù)器知道我們使用的是 /xyz 而不是物理路徑 /abc/def
          RewriteBase /xyz

          # 重寫規(guī)則
          RewriteRule ^oldstuff\.html$ newstuff.html

          上述例子中,對/xyz/oldstuff.html的請求被正確地重寫為對物理文件/abc/def/newstuff.html的請求。

          僅供Apache Hacker們參考

          以下列出了內(nèi)部處理的詳細(xì)步驟:

          請求:
          /xyz/oldstuff.html

          內(nèi)部處理過程:
          /xyz/oldstuff.html -> /abc/def/oldstuff.html (per-server Alias)
          /abc/def/oldstuff.html -> /abc/def/newstuff.html (per-dir RewriteRule)
          /abc/def/newstuff.html -> /xyz/newstuff.html (per-dir RewriteBase)
          /xyz/newstuff.html -> /abc/def/newstuff.html (per-server Alias)

          結(jié)果:
          /abc/def/newstuff.html

          雖然這個過程看來很繁復(fù),但是由于目錄級重寫的到來時機(jī)已經(jīng)太晚了,它不得不把這個(重寫)請求重新注入到 Apache核心中,所以Apache內(nèi)部確實是這樣處理的。但是:它的開銷并不象看起來的那樣大,因為重新注入完全在Apache服務(wù)器內(nèi)部進(jìn)行,而且 這樣的過程在Apache內(nèi)部也為其他許多操作所使用。所以,你可以充分信任其設(shè)計和實現(xiàn)是正確的。

          RewriteCond 指令

          說明 定義重寫發(fā)生的條件
          語法 RewriteCond TestStringCondPattern [flags]
          作用域 server config, virtual host, directory, .htaccess
          覆蓋項 FileInfo
          狀態(tài) 擴(kuò)展(E)
          模塊 mod_rewrite

          RewriteCond指令定義了規(guī)則生效的條件,即在一個RewriteRule指令之前可以有一個或多個RewriteCond指令。條件之后的重寫規(guī)則僅在當(dāng)前URI與Pattern匹配并且滿足此處的條件(TestString能夠與CondPattern匹配)時才會起作用。

          TestString是一個純文本的字符串,但是還可以包含下列可擴(kuò)展的成分:

          • RewriteRule反向引用 ,引用方法是:

            $N

            (0 <= N <= 9)引用當(dāng)前(帶有若干RewriteRule指令的)RewriteCond中的與Pattern匹配的分組成分(圓括號!)。
          • RewriteCond反向引用 ,引用方法是:

            %N

            (1 <= N <= 9)引用當(dāng)前若干RewriteCond條件中最后符合的條件中的分組成分(圓括號!)。
          • RewriteMap擴(kuò)展 ,引用方法是:

            ${mapname:key|default}

            細(xì)節(jié)請參見RewriteMap 指令
          • 服務(wù)器變量 ,引用方法是:

            %{NAME_OF_VARIABLE}

            NAME_OF_VARIABLE可以是下表列出的字符串之一:
            HTTP頭連接與請求
            HTTP_USER_AGENT
            HTTP_REFERER
            HTTP_COOKIE
            HTTP_FORWARDED
            HTTP_HOST
            HTTP_PROXY_CONNECTION
            HTTP_ACCEPT
            REMOTE_ADDR
            REMOTE_HOST
            REMOTE_PORT
            REMOTE_USER
            REMOTE_IDENT
            REQUEST_METHOD
            SCRIPT_FILENAME
            PATH_INFO
            QUERY_STRING
            AUTH_TYPE

            服務(wù)器自身日期和時間其它
            DOCUMENT_ROOT
            SERVER_ADMIN
            SERVER_NAME
            SERVER_ADDR
            SERVER_PORT
            SERVER_PROTOCOL
            SERVER_SOFTWARE
            TIME_YEAR
            TIME_MON
            TIME_DAY
            TIME_HOUR
            TIME_MIN
            TIME_SEC
            TIME_WDAY
            TIME
            API_VERSION
            THE_REQUEST
            REQUEST_URI
            REQUEST_FILENAME
            IS_SUBREQ
            HTTPS

            這些變量都對應(yīng)于類似命名的HTTP MIME頭、Apache服務(wù)器的C變量、Unix系統(tǒng)中的struct tm字段,其中的大多數(shù)在其他的手冊或者CGI規(guī)范中都有說明。 其中為mod_rewrite所特有的變量如下:

            IS_SUBREQ
            如果正在處理的請求是一個子請求,它將包含字符串"true",否則就是"false"。模塊為了解析URI中的附加文件,可能會產(chǎn)生子請求。
            API_VERSION
            這是正在使用中的Apache模塊API(服務(wù)器和模塊之間內(nèi)部接口)的版本, 其定義位于include/ap_mmn.h中。此模塊API版本對應(yīng)于正在使用的Apache的版本(比如在Apache 1.3.14的發(fā)行版中這個值是19990320:10)。 通常,對它感興趣的是模塊的開發(fā)者。
            THE_REQUEST
            這是由瀏覽器發(fā)送的完整的HTTP請求行(比如:"GET /index.html HTTP/1.1")。它不包含任何瀏覽器發(fā)送的其它頭信息。
            REQUEST_URI
            這是在HTTP請求行中所請求的資源(比如上述例子中的"/index.html")。
            REQUEST_FILENAME
            這是與請求相匹配的完整的本地文件系統(tǒng)的文件路徑名。
            HTTPS
            如果連接使用了SSL/TLS,它將包含字符串"on",否則就是"off"(無論mod_ssl是否已經(jīng)加載,該變量都可以安全的使用)。

          其它注意事項:

          1. SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的——即Apache服務(wù)器內(nèi)部的request_rec結(jié)構(gòu)中的filename字段。 第一個就是大家都知道的CGI變量名,而第二個則是REQUEST_URI(request_rec結(jié)構(gòu)中的uri字段)的一個副本。
          2. 特殊形式:%{ENV:variable} ,其中的variable可以是任意環(huán)境變量。它是通過查找Apache內(nèi)部結(jié)構(gòu)或者(如果沒找到的話)由Apache服務(wù)器進(jìn)程通過getenv()得到的。
          3. 特殊形式:%{SSL:variable} ,其中的variable可以是一個SSL環(huán)境變量的名字,無論mod_ssl模塊是否已經(jīng)加載都可以使用(未加載時為空字符串)。比如:%{SSL:SSL_CIPHER_USEKEYSIZE}將會被替換為128
          4. 特殊形式:%{HTTP:header} ,其中的header可以是任意HTTP MIME頭的名稱。它總是可以通過查找HTTP請求而得到。比如:%{HTTP:Proxy-Connection}將被替換為Proxy-Connection:HTTP頭的值。
          5. 預(yù)設(shè)形式:%{LA-U:variable}variable的最終值在執(zhí)行一個內(nèi)部(基于URL的)子請求后確定。 當(dāng)需要使用一個目前未知但是會在之后的過程中設(shè)置的變量的時候,就可以使用這個方法。

            例如,需要在服務(wù)器級配置(httpd.conf文件)中根據(jù)REMOTE_USER變量進(jìn)行重寫, 就必須使用%{LA-U:REMOTE_USER}。因為此變量是由URL重寫(mod_rewrite)步驟之后的認(rèn)證步驟設(shè)置的。 但是另一方面,因為mod_rewrite是通過API修正步驟來實現(xiàn)目錄級(.htaccess文件)配置的, 而認(rèn)證步驟先于API修正步驟,所以可以用%{REMOTE_USER}

          6. 預(yù)設(shè)形式:%{LA-F:variable}variable的最終值在執(zhí)行一個內(nèi)部(基于文件名的)子請求后確定。 大多數(shù)情況下和上述的LA-U是相同的。

          CondPattern是條件模式,即一個應(yīng)用于當(dāng)前TestString實例的正則表達(dá)式。TestString將被首先計算,然后再與CondPattern匹配。

          注意: CondPattern是一個perl兼容的正則表達(dá)式,但是還有若干增補(bǔ):

          1. 可以在CondPattern串的開頭使用'!'(驚嘆號)來指定不匹配
          2. CondPatterns有若干特殊的變種。除了正則表達(dá)式的標(biāo)準(zhǔn)用法,還有下列用法:
            • '<CondPattern'(詞典順序的小于)
              CondPattern視為純字符串,與TestString按詞典順序進(jìn)行比較。如果TestString小于CondPattern則為真。
            • '>CondPattern'(詞典順序的大于)
              CondPattern視為純字符串,與TestString按詞典順序進(jìn)行比較。如果TestString大于CondPattern則為真。
            • '=CondPattern'(詞典順序的等于)
              CondPattern視為純字符串,與TestString按詞典順序進(jìn)行比較。如果TestString等于CondPattern(兩個字符串逐個字符地完全相等)則為真。如果CondPattern""(兩個雙引號),則TestString將與空字符串進(jìn)行比較。
            • '-d'(目錄)
              TestString視為一個路徑名并測試它是否為一個存在的目錄。
            • '-f'(常規(guī)文件)
              TestString視為一個路徑名并測試它是否為一個存在的常規(guī)文件。
            • '-s'(非空的常規(guī)文件)
              TestString視為一個路徑名并測試它是否為一個存在的、尺寸大于0的常規(guī)文件。
            • '-l'(符號連接)
              TestString視為一個路徑名并測試它是否為一個存在的符號連接。
            • '-x'(可執(zhí)行)
              TestString視為一個路徑名并測試它是否為一個存在的、具有可執(zhí)行權(quán)限的文件。該權(quán)限由操作系統(tǒng)檢測。
            • '-F'(對子請求存在的文件)
              檢查TestString是否為一個有效的文件,而且可以在服務(wù)器當(dāng)前的訪問控制配置下被訪問。它使用一個內(nèi)部子請求來做檢查,由于會降低服務(wù)器的性能,所以請謹(jǐn)慎使用!
            • '-U'(對子請求存在的URL)
              檢查TestString是否為一個有效的URL,而且可以在服務(wù)器當(dāng)前的訪問控制配置下被訪問。它使用一個內(nèi)部子請求來做檢查,由于會降低服務(wù)器的性能,所以請謹(jǐn)慎使用!

            注意

            所有這些測試都可以用驚嘆號作前綴('!')以實現(xiàn)測試條件的反轉(zhuǎn)。
          3. 還可以在CondPattern之后追加特殊的標(biāo)記[flags]作為RewriteCond指令的第三個參數(shù)。flags是一個以逗號分隔的以下標(biāo)記的列表:
            • 'nocase|NC'(忽略大小寫)
              它使測試忽略大小寫,擴(kuò)展后的TestStringCondPattern中'A-Z' 和'a-z'是沒有區(qū)別的。此標(biāo)記僅用于TestStringCondPattern的比較,而對文件系統(tǒng)和子請求的檢查不起作用。
            • 'ornext|OR'(或下一條件)
              它以O(shè)R方式組合若干規(guī)則的條件,而不是隱含的AND。典型的例子如下:
              RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]
              RewriteCond %{REMOTE_HOST} ^host2.* [OR]
              RewriteCond %{REMOTE_HOST} ^host3.*
              RewriteRule ... 針對這3個主機(jī)的規(guī)則集 ...
              如果不用這個標(biāo)記,你就必須要書寫三次條件/規(guī)則對。

          舉例

          如果要按請求頭中的"User-Agent:"重寫一個站點的主頁,可以這樣寫:

          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]

          解釋:如果你使用的瀏覽器識別標(biāo)志是'Mozilla',則你將得到內(nèi)容最大化的主頁(含有Frames等等)。如果你使用的是 (基于終端的)Lynx,則你得到的是內(nèi)容最小化的主頁(不含table等等)。如果上述條件都不滿足(使用的是其他瀏覽器),則你得到的是一個標(biāo)準(zhǔn)的主 頁。

          RewriteEngine 指令

          說明 打開或關(guān)閉運行時的重寫引擎
          語法 RewriteEngine on|off
          默認(rèn)值 RewriteEngine off
          作用域 server config, virtual host, directory, .htaccess
          覆蓋項 FileInfo
          狀態(tài) 擴(kuò)展(E)
          模塊 mod_rewrite

          RewriteEngine指令打開或關(guān)閉運行時的重寫引擎。如果設(shè)置為off,則此模塊在運行時不執(zhí)行任何重寫操作, 同時也不更新SCRIPT_URx環(huán)境變量。

          使用該指令可以使此模塊無效,而無須注釋所有的RewriteRule指令!

          注意:默認(rèn)情況下,重寫配置是不可繼承的,也就是必須在每個需要使用重寫引擎的虛擬主機(jī)中設(shè)置一個RewriteEngine on指令。

          RewriteLock 指令

          說明 設(shè)置RewriteMap同步所使用的鎖文件名
          語法 RewriteLock file-path
          作用域 server config
          狀態(tài) 擴(kuò)展(E)
          模塊 mod_rewrite

          此指令設(shè)置mod_rewrite為了和RewriteMap程序通訊而使用的同步鎖文件的名稱。 在需要使用重寫映射表程序(rewriting map-program)時,它必須是一個本地路徑(而不能是一個NFS掛接設(shè)備)。對其他類型的重寫映射表(rewriting map),則無此要求。

          RewriteLog 指令

          說明 設(shè)置重寫引擎日志的文件名
          語法 RewriteLog file-path
          作用域 server config, virtual host
          狀態(tài) 擴(kuò)展(E)
          模塊 mod_rewrite

          RewriteLog指令設(shè)置用于記錄所有重寫操作的日志文件的名稱。如果此文件名不以斜杠('/')開頭,則它是相對于Server Root的,此指令應(yīng)該在每個服務(wù)器級別的配置中僅僅出現(xiàn)一次。

          如果要關(guān)閉對重寫操作的記錄,不推薦將Filename設(shè)為/dev/null ,因為,雖然重寫引擎不能輸出記錄了,但仍會在內(nèi)部建立這個日志文件,這樣會使服務(wù)器速度降低,而且對管理員毫無益處!要關(guān)閉日志,可以刪除或注解RewriteLog指令, 或者使用"RewriteLogLevel 0"的設(shè)置

          安全

          參見安全方面的提示文檔,其中講述了為什么如果存放日志的目錄對除了啟動服務(wù)器以外的用戶是可寫的會帶來安全隱患。

          示例

          RewriteLog "/usr/local/var/apache/logs/rewrite.log"

          RewriteLogLevel 指令

          說明 設(shè)置重寫日志的詳細(xì)程度
          語法 RewriteLogLevel Level
          默認(rèn)值 RewriteLogLevel 0
          作用域 server config, virtual host
          狀態(tài) 擴(kuò)展(E)
          模塊 mod_rewrite

          RewriteLogLevel指令設(shè)置重寫引擎日志的詳細(xì)程度的級別。0(默認(rèn)級別)意味著不記錄,而9或更大的值意味著記錄所有操作。

          要關(guān)閉重寫引擎日志,可以簡單地將Level設(shè)為0,以關(guān)閉所有重寫操作的記錄。

          較高的Level值會使Apache服務(wù)器速度急劇下降!大于2的Level值只用于調(diào)試目的!

          示例

          RewriteLogLevel 3

          RewriteMap 指令

          說明 定義用于關(guān)鍵詞查找的映射函數(shù)
          語法 RewriteMap MapNameMapType:MapSource
          作用域 server config, virtual host
          狀態(tài) 擴(kuò)展(E)
          模塊 mod_rewrite
          兼容性 Apache 2.0.41 及以后的版本中可以使用不同的dbm類型

          RewriteMap指令定義了一個映射表(Rewriting Map),映射函數(shù)將使用該表來查找關(guān)鍵字然后插入/替換字段。此查找操作的源可以是多種類型。

          MapName 是映射表的名稱,指定了一個映射函數(shù),用于重寫規(guī)則的字符串替換,它可以是下列形式之一:

          ${ MapName : LookupKey }
          ${ MapName : LookupKey | DefaultValue }

          如果使用了這樣的形式,則會在MapName中查找關(guān)鍵詞LookupKey。如果找到了,則被替換成SubstValue; 如果沒有找到,則被替換成DefaultValue,如果沒有指定DefaultValue,則被替換成空字符串。

          例如,你可能定義這樣一個RewriteMap

          RewriteMap examplemap txt:/path/to/file/map.txt

          然后你就可以像下面這樣在RewriteRule中使用該映射:

          RewriteRule ^/ex/(.*) ${examplemap:$1}

          可以使用下列MapTypeMapSource的組合:

          • 標(biāo)準(zhǔn)純文本
            MapType: txt, MapSource: 有效的Unix文件系統(tǒng)文件名

            這是重寫映射表的標(biāo)準(zhǔn)形式。MapSource是一個純文本文件,包含空行、注釋行(以字符'#'打頭),以及每行一個的替換對,如下所示:

            MatchingKeySubstValue

            例子

            ##  map.txt -- rewriting map

            Ralf.S.Engelschall rse # Bastard Operator From Hell
            Mr.Joe.Average joe # Mr. Average

            RewriteMap real-to-user txt:/path/to/file/map.txt

          • 隨機(jī)純文本
            MapType: rnd, MapSource: 有效的Unix文件系統(tǒng)文件名

            這個與上述的標(biāo)準(zhǔn)純文本很相似,但它有一個特殊的后處理特性:查找完畢后,會解析其中包含的"|"符號(含義為"或")。 也就是說,會隨機(jī)地選擇其中之一作為返回值。雖然這看似毫無意義,但設(shè)計它的意圖是在一個查找值是服務(wù)器名稱的反向代理環(huán)境中實現(xiàn)負(fù)載平衡。

            例子

            映射文件

            ##  map.txt -- rewriting map

            static www1|www2|www3|www4
            dynamic www5|www6

            配置指令

            RewriteMap servers rnd:/path/to/file/map.txt

            RewriteRule ^/(.*\.(png|gif|jpg)) http://${servers:static}/$1 [NC,P,L]
            RewriteRule ^/(.*) http://${servers:dynamic}/$1 [P,L]

          • 散列文件
            MapType: dbm[=type], MapSource: 有效的Unix文件系統(tǒng)文件名

            這里的源是一個二進(jìn)制格式的DBM文件,包含了與純文本相同的內(nèi)容,但是因為它有優(yōu)化了的特殊表現(xiàn)形式,使它的查找速度明顯快得多。 此type可以是sdbm, gdbm, ndbm, db(由編譯時配置決定)。如果省略type,則使用編譯時選擇的缺省值。 你可以使用任何DBM工具或者下列Perl腳本來創(chuàng)建這個文件,但必須保證DBM的類型正確。建立NDBM文件的例子如下:

            #!/path/to/bin/perl
            ##
            ## txt2dbm -- 將 txt 映射表轉(zhuǎn)換為 dbm 格式
            ##

            use NDBM_File;
            use Fcntl;

            ($txtmap, $dbmmap) = @ARGV;

            open(TXT, "<$txtmap") or die "Couldn't open $txtmap!\n";
            tie (%DB, 'NDBM_File', $dbmmap,O_RDWR|O_TRUNC|O_CREAT, 0644)
            or die "Couldn't create $dbmmap!\n";

            while (<TXT>) {
            next if (/^\s*#/ or /^\s*$/);
            $DB{$1} = $2 if (/^\s*(\S+)\s+(\S+)/);
            }

            untie %DB;
            close(TXT);

            $ txt2dbm map.txt map.db

          • 內(nèi)部函數(shù)
            MapType: int, MapSource: Apache內(nèi)部函數(shù)

            這里的源是一個Apache的內(nèi)部函數(shù)。目前,還不能由你自己建立,只能使用下列已經(jīng)存在的函數(shù):

            • toupper:
              轉(zhuǎn)換查找關(guān)鍵詞為大寫
            • tolower:
              轉(zhuǎn)換查找關(guān)鍵詞為小寫
            • escape:
              轉(zhuǎn)換查找關(guān)鍵詞中的特殊字符為十六進(jìn)制編碼
            • unescape:
              轉(zhuǎn)換查找關(guān)鍵詞中的十六進(jìn)制編碼為特殊字符
          • 外部的重寫程序
            MapType: prg, MapSource: 有效的Unix文件系統(tǒng)文件名

            這里的源是一個程序,而不是一個映射表文件。程序設(shè)計語言可以隨意選擇,但最終結(jié)果必須是可執(zhí)行的(或者是目標(biāo)代碼,或者是首行為'#!/path/to/interpreter'的腳本)。

            此程序僅在Apache服務(wù)器啟動時啟動一次,隨后通過stdinstdout文件句柄與重寫引擎交互。 對每個映射函數(shù)的查找操作,它從stdin接收以回車結(jié)束的查找關(guān)鍵詞,然后把查找的結(jié)果以回車結(jié)束反饋到stdout,如果查找失敗,則返回四個字符的字符串"NULL"(對給定的關(guān)鍵詞沒有對應(yīng)的值)。此程序的最簡單形式是一個1:1的映射(即:key == value),例如:

            #!/usr/bin/perl
            $| = 1;
            while (<STDIN>) {
            # ...在這里放置轉(zhuǎn)換和查找...
            print $_;
            }

            但是必須注意:

            1. "簡單就是美"(KISS: Keep it simple, stupid!)。此程序的崩潰會直接導(dǎo)致Apache服務(wù)器的崩潰。
            2. 絕不要對stdout做I/O緩沖(一個常見的錯誤),它會導(dǎo)致死循環(huán)!所以上述例子中才會使用"$|=1"來預(yù)防。
            3. 使用RewriteLock指令定義一個鎖文件,用于同步mod_rewrite和此程序之間的通訊。默認(rèn)是沒有同步操作的。

          RewriteMap指令可以多次出現(xiàn)。對每個映射函數(shù)都可以使用一個RewriteMap指令來定義其重寫映射表。雖然不能在目錄上下文(per-directory context)中定義映射表,但是完全可以在其中使用映射表。

          注意

          對于純文本和DBM格式的文件,已經(jīng)查找過的關(guān)鍵詞會被緩存在內(nèi)核中,直到映射表的mtime改變了或者服務(wù)器重啟了。這樣,你可以把每個請求都會用到的映射函數(shù)放在規(guī)則中,這是沒有問題的,因為外部查找只進(jìn)行一次。

          RewriteOptions 指令

          說明 為重寫引擎設(shè)置一些特殊的選項
          語法 RewriteOptions Options
          作用域 server config, virtual host, directory, .htaccess
          覆蓋項 FileInfo
          狀態(tài) 擴(kuò)展(E)
          模塊 mod_rewrite
          兼容性 MaxRedirects在2.1及以后的版本中已經(jīng)不可用

          RewriteOptions指令為當(dāng)前服務(wù)器級和目錄級的配置設(shè)置一些選項。Option當(dāng)前僅可以是如下值:

          inherit
          此值強(qiáng)制當(dāng)前配置繼承其父配置。在虛擬主機(jī)級配置中,它意味著主服務(wù)器的映射表、條件和規(guī)則可以被繼承。在目錄級配置中,它意味著其父目錄的.htaccess中的條件和規(guī)則可以被繼承。

          RewriteRule 指令

          說明 為重寫引擎定義重寫規(guī)則
          語法 RewriteRule PatternSubstitution [flags]
          作用域 server config, virtual host, directory, .htaccess
          覆蓋項 FileInfo
          狀態(tài) 擴(kuò)展(E)
          模塊 mod_rewrite
          兼容性 cookie-flag在Apache 2.0.40及以后的版本中可用

          RewriteRule指令是重寫引擎的根本。此指令可以多次使用。每個指令定義一個簡單的重寫規(guī)則。這些規(guī)則的定義順序尤為重要——在運行時,規(guī)則是按這個順序逐一生效的。

          Pattern 是一個作用于當(dāng)前URL的perl兼容的正則表達(dá)式。"當(dāng)前URL"是指該規(guī)則生效時刻的URL的值。它可能與被請求的URL截然不同,因為其他規(guī)則可能在此之前已經(jīng)發(fā)生匹配并對它做了改動。

          正則表達(dá)式的一些用法示例:

          										文本
          										
          . 任意一個單字符
          [chars] 字符類: "chars"中的任意一個字符
          [^chars] 字符類: 不在"chars"中的字符
          text1|text2 選擇: text1 或 text2

          量詞
          ? 前面的字符出現(xiàn) 0 或 1 次
          * 前面的字符出現(xiàn) 0 或 N 次(N > 0)
          + 前面的字符出現(xiàn) 1 或 N 次(N > 1)

          分組
          (text) text 組
          (常用于設(shè)置一個選擇的邊界,或用于生成后引用:
          在RewriteRule中可以用 $N 引用第N個分組)


          ^ 錨定到行首
          $ 錨定到行尾

          轉(zhuǎn)義
          \c 對給定的字符c進(jìn)行轉(zhuǎn)義
          (比如對".[]()"進(jìn)行轉(zhuǎn)義,等等)

          更多有關(guān)正則表達(dá)式的資料請參見perl正則表達(dá)式手冊頁("perldoc perlre")。另外,在mod_rewrite中,還可以使用否字符('!')前綴實現(xiàn)反轉(zhuǎn)。比如:"如果當(dāng)前URL與模式相匹配"它用于使用否定式匹配模式較容易描述的某些情況,或者作為最后一條規(guī)則。

          注意

          使用否字符以反轉(zhuǎn)匹配模式時,匹配模式中不能使用分組的通配成分。由于模式不匹配而使分組的內(nèi)容是空的,所以它是不可能實現(xiàn)的。 因此,如果使用了否定式匹配模式,那么后繼的字符串中就不能使用$N

          重寫規(guī)則中的Substitution是當(dāng)原始URL與Pattern相匹配時,用來替代(或替換)的字符串。除了純文本,還可以包含:

          1. Pattern的反向引用($N)
          2. 對最后匹配的RewriteCond的反向引用(%N)
          3. 規(guī)則條件測試字符串(%{VARNAME})中的服務(wù)器變量
          4. 映射函數(shù)調(diào)用(${mapname:key|default})

          反向引用的$N(N=0..9)是指用Pattern匹配的第N組的內(nèi)容去替換URL。服務(wù)器變量與RewriteCond指令的TestString相同。映射函數(shù)由RewriteMap指令決定,其說明也參見該指令。這三種類型變量按上面列表中的順序被展開。

          如上所述,所有的重寫規(guī)則都是按配置文件中的定義順序作用于Substitution的。URL被Substitution完全替換,并繼續(xù)處理直到所有規(guī)則處理完畢,除非用L標(biāo)記顯式地終結(jié)(見下文)。

          '-'是一個特殊的替換串,意思是不替換。它可以用于僅僅匹配某些URL而無須替換的情況,比如,在發(fā)生替換前,允許以C(chain)標(biāo)記連接的多個匹配模式同時起作用。

          此外,在Substitution之后還可以追加[flags]標(biāo)記作為RewriteRule指令的第三個參數(shù)。Flags是一個包含以逗號分隔的下列標(biāo)記的列表:

          注意:絕對URL的替換

          當(dāng)替換字段以"http://thishost[:thisport]"作為前綴時,mod_rewrite會將它自動剝離出去。在配合生成主機(jī)名部分的映射函數(shù)使用的時候,這個對隱含的外部重定向URL的簡化操作是有用的而且是重要的。下面的第一個例子有助于理解這點。

          謹(jǐn)記:由于此功能的存在,以"http://thishost"為前綴的無條件外部重定向到自身所在的服務(wù)器是無效的。要實現(xiàn)一個到自身的重定向,必須使用R標(biāo)記。

          注意:查詢字符串

          Pattern不會按照查詢字符串進(jìn)行匹配。為了達(dá)到這個目的,你必須使用一個帶有%{QUERY_STRING}變量的RewriteCond指令。當(dāng)然,你也可以在替換字符串中創(chuàng)建包含查詢字符串的URL:在替換字符串串中使用問號,以標(biāo)明其后的部分應(yīng)該被重新注入到QUERY_STRING中。而要刪除一個已有的請求串,則可以用問號來終結(jié)替換字符串。為了聯(lián)合新舊查詢字符串,請使用[QSA]標(biāo)志。

          以下是所有可能的替換組合及其含義:

          在服務(wù)器級配置中(httpd.conf)
          對給定的請求"GET /somepath/pathinfo":

          										給定的規(guī)則
          										得到的替換字符串
          										
          ---------------------------------------------- ----------------------------------
          ^/somepath(.*) otherpath$1 非法,不被支持

          ^/somepath(.*) otherpath$1 [R] 非法,不被支持

          ^/somepath(.*) otherpath$1 [P] 非法,不被支持
          ---------------------------------------------- ----------------------------------
          ^/somepath(.*) /otherpath$1 /otherpath/pathinfo

          ^/somepath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo
          通過外部重定向

          ^/somepath(.*) /otherpath$1 [P] 毫無意義,不被支持
          ---------------------------------------------- ----------------------------------
          ^/somepath(.*) http://thishost/otherpath$1 /otherpath/pathinfo

          ^/somepath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo
          通過外部重定向

          ^/somepath(.*) http://thishost/otherpath$1 [P] 毫無意義,不被支持
          ---------------------------------------------- ----------------------------------
          ^/somepath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo
          通過外部重定向

          ^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
          通過外部重定向
          ([R]標(biāo)記是多余的)

          ^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
          通過內(nèi)部代理

          /somepath的目錄級配置中
          (也就是/physical/path/to/somepath/.htacccess文件中含有:RewriteBase /somepath)
          對給定的請求"GET /somepath/localpath/pathinfo":

          										給定的規(guī)則
          										得到的替換字符串
          										
          ---------------------------------------------- ----------------------------------
          ^localpath(.*) otherpath$1 /somepath/otherpath/pathinfo

          ^localpath(.*) otherpath$1 [R] http://thishost/somepath/otherpath/pathinfo
          通過外部重定向

          ^localpath(.*) otherpath$1 [P] 毫無意義,不被支持
          ---------------------------------------------- ----------------------------------
          ^localpath(.*) /otherpath$1 /otherpath/pathinfo

          ^localpath(.*) /otherpath$1 [R] http://thishost/otherpath/pathinfo
          通過外部重定向

          ^localpath(.*) /otherpath$1 [P] 毫無意義,不被支持
          ---------------------------------------------- ----------------------------------
          ^localpath(.*) http://thishost/otherpath$1 /otherpath/pathinfo

          ^localpath(.*) http://thishost/otherpath$1 [R] http://thishost/otherpath/pathinfo
          通過外部重定向

          ^localpath(.*) http://thishost/otherpath$1 [P] 毫無意義,不被支持
          ---------------------------------------------- ----------------------------------
          ^localpath(.*) http://otherhost/otherpath$1 http://otherhost/otherpath/pathinfo
          通過外部重定向

          ^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
          通過外部重定向
          ([R]標(biāo)記是多余的)

          ^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
          通過內(nèi)部代理
          posted on 2011-02-16 09:01 禮物 閱讀(1188) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。

          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 宁蒗| 永清县| 习水县| 乌拉特前旗| 望谟县| 邢台市| 田林县| 互助| 铁力市| 尤溪县| 祁阳县| 茂名市| 五华县| 光泽县| 汤原县| 天柱县| 上饶市| 克什克腾旗| 钟祥市| 当涂县| 基隆市| 隆回县| 阳原县| 波密县| 洪江市| 尼勒克县| 永福县| 即墨市| 大兴区| 邹平县| 陈巴尔虎旗| 丽江市| 乌审旗| 英山县| 百色市| 宣威市| 琼结县| 新乐市| 阳谷县| 南雄市| 大冶市|