Apache HTTP Server 版本2.2
本文闡述Apache如何根據(jù)URL地址定位到文件在文件系統(tǒng)中的位置。
相關(guān)模塊 | 相關(guān)指令 |
---|---|
Apache根據(jù)請求定位文件的默認(rèn)操作是:取出URL路徑(即URL中主機(jī)名和端口后面的部分)附加到由DocumentRoot
指定的文件系統(tǒng)路徑后面。這樣就組成了在網(wǎng)上所看見的基本文件樹結(jié)構(gòu)。
如果服務(wù)器有多個虛擬主機(jī),則Apache會使用下述兩種方法之一:使用每個虛擬主機(jī)自己的DocumentRoot
來組成文件系統(tǒng)路徑,或者使用由mod_vhost_alias
提供的指令基于IP地址或主機(jī)名動態(tài)地定位文件。
實(shí)際應(yīng)用中,經(jīng)常有必要允許網(wǎng)絡(luò)對DocumentRoot
以外的文件進(jìn)行訪問。對此,Apache提供了多種方法,在Unix系統(tǒng)中,可以在文件系統(tǒng)的DocumentRoot
目錄下放置符號連接以訪問其外部文件,考慮到安全問題,這種方法僅在相應(yīng)目錄的Options
指令中設(shè)置了FollowSymLinks
或SymLinksIfOwnerMatch
時才有效。
另外,使用Alias
指令可以將文件系統(tǒng)的任何部分映射到網(wǎng)絡(luò)空間中。例如,這個命令
Alias /docs /var/web
可以把URL http://www.example.com/docs/dir/file.html
映射為/var/web/dir/file.html
。ScriptAlias
指令功能相似,而且使所有目標(biāo)路徑下的所有文件被視為CGI腳本。
AliasMatch
和ScriptAliasMatch
指令可以實(shí)現(xiàn)基于正則表達(dá)式的匹配和替換,以提供更大的靈活性。例如:
ScriptAliasMatch ^/~([a-zA-Z0-9]+)/cgi-bin/(.+) /home/$1/cgi-bin/$2
上述命令可以將http://example.com/~user/cgi-bin/script.cgi
映射到/home/user/cgi-bin/script.cgi
,并視之為CGI腳本。
在Unix系統(tǒng)中,一個特定用戶"user"的主目錄通常是"~user/
"模塊mod_userdir
在網(wǎng)絡(luò)上沿用了這個概念,允許使用URL訪問位于各用戶主目錄下的文件,例如:
http://www.example.com/~user/file.html
出于安全原因,不應(yīng)該給予網(wǎng)絡(luò)用戶直接操作主目錄的權(quán)限,而應(yīng)該在用戶主目錄下新建一個目錄,把網(wǎng)絡(luò)文件放在這個新建的目錄中,并用UserDir
指令告訴服務(wù)器。缺省的用戶目錄設(shè)置是"Userdir public_html
",因此,上述例子中的URL會映射到/home/user/public_html/file.html
,其中/home/user/
是/etc/passwd
指定的用戶主目錄。
當(dāng)/etc/passwd
沒有指定主目錄,那就要用到Userdir
指令的另幾種形式。
有些人覺得符號"~"(時常會被編碼為%7e
)很別扭,希望用其他形式來表達(dá)用戶目錄。雖然模塊mod_userdir
并不支持,但是,如果合理規(guī)劃服務(wù)器上的用戶目錄,則還是有可能用AliasMatch
指令來達(dá)到這個目的。例如,如果希望將http://www.example.com/upages/user/file.html
映射到/home/user/public_html/file.html
,可以這樣使用AliasMatch
指令:
AliasMatch ^/upages/([a-zA-Z0-9]+)/?(.*) /home/$1/public_html/$2
上述指令都指示Apache返回給客戶文件系統(tǒng)的某個特定內(nèi)容,但是有時候,需要通知客戶其請求的內(nèi)容位于其他URL,并使客戶產(chǎn)生新的對其他URL的請求,這種機(jī)制稱為重定向(redirection),可以用Redirect
指令實(shí)現(xiàn)。例如:如果DocumentRoot
的目錄/foo/
被轉(zhuǎn)移到了/bar/
,則可以這樣引導(dǎo)客戶訪問新的位置:
Redirect permanent /foo/ http://www.example.com/bar/
這個命令重定向任何以/foo/
開頭的URL路徑到位于同一個服務(wù)器www.example.com
的/bar/
。當(dāng)然,可以重定向到任何其它服務(wù)器,而不僅僅是原來的那個。
Apache還提供了RedirectMatch
指令來解決復(fù)雜的重定向問題。例如,要重定向?qū)φ军c(diǎn)主頁的請求到其他站點(diǎn),而保留其他所有請求,可以這樣配置:
RedirectMatch permanent ^/$ http://www.example.com/startpage.html
另一種方法是,暫時地重定向站點(diǎn)的所有頁面到一個特定頁面,如:
RedirectMatch temp .* http://othersite.example.com/startpage.html
Apache還允許將遠(yuǎn)程文檔納入本地服務(wù)器的網(wǎng)絡(luò)空間中,因?yàn)閃eb服務(wù)器扮演一個代理服務(wù)器的角色(從遠(yuǎn)程服務(wù)器取得文檔并返回給客戶),所以這種機(jī)制被稱為反向代理(reverse proxying),不同于標(biāo)準(zhǔn)代理的是,在客戶看來,他請求的文檔似乎原本就位于這個反向代理服務(wù)器上。
下例演示了當(dāng)客戶請求位于/foo/
目錄下的文檔時,服務(wù)器從internal.example.com
的/bar/
目錄下取回文檔并返回給客戶,似乎文檔原本就在本地服務(wù)器上:
ProxyPass /foo/ http://internal.example.com/bar/
ProxyPassReverse /foo/ http://internal.example.com/bar/
ProxyPassReverseCookieDomain internal.example.com public.example.com
ProxyPassReverseCookiePath /foo/ /bar/
ProxyPass
指令使服務(wù)器正確地取回文檔,同時,ProxyPassReverse
指令改變了起始于internal.example.com
的請求,使之指向本地服務(wù)器上的目錄。同樣,ProxyPassReverseCookieDomain
和ProxyPassReverseCookieDomain
指令將會改變后端服務(wù)器設(shè)置的cookie 。
需要注意的很重要的一點(diǎn)是,被取回的文檔中的連接是不會被改寫的,因此,文檔中的所有絕對路徑連接會突破代理機(jī)制而直接從internal.example.com
取得。一個第三方模塊mod_proxy_html可以用于重寫HTML和XHTML連接。
mod_rewrite
模塊提供了更強(qiáng)大的URL重寫引擎,可以根據(jù)請求中諸如瀏覽器類型、源IP地址等特征來決定最終提交給客戶的內(nèi)容,還可以使用外部數(shù)據(jù)庫或程序來決定如何處理一個請求,并可以執(zhí)行上述的所有三種映射:內(nèi)部重定向(aliases)、外部重定向、代理。許多實(shí)用程序都用到了這個模塊,詳細(xì)論述參見:URL重寫指南。
從URL到文件系統(tǒng)的匹配失敗是不可避免的,其產(chǎn)生原因有多種。有時是文檔被轉(zhuǎn)移了,對此最好是用URL重定向來引導(dǎo)用戶訪問新的位置,這樣,雖然資源已經(jīng)轉(zhuǎn)移到新的位置,但是原來的書簽和連接仍然有效。
另一種常見的原因是瀏覽器地址欄或者HTML連接中的URL被拼寫錯了,Apache提供了mod_speling
模塊來幫助解決這個問題,它會接管"File Not Found"錯誤并查找相似文件,如果找到了唯一的一個,則會重定向到這個文件,如果不止一個,則會列一張表反饋給用戶。
mod_speling
的一個很有用的特性是,它可以忽略大小寫查找文件,對不注意URL大小寫的用戶和unix文件系統(tǒng)尤為實(shí)用。但是,糾正偶然的URL錯誤會給服務(wù)器帶來額外的負(fù)擔(dān),因?yàn)槊看?不正確"的請求都將引發(fā)URL重定向和來自客戶的新請求。
如果所有的努力都失敗了,Apache會返回一個出錯信息頁面,其狀態(tài)碼為"404"(文件沒找到),其頁面內(nèi)容取決于ErrorDocument
指令,并可以靈活地自定義其形式,詳見:自定義錯誤響應(yīng)。