本文將介紹Apache HTTP Server如何使用請求的URL來確定從中提供檔的檔系統位置。
DocumentRoot
在決定為給定請求提供什麼檔時,httpd的默認行為是獲取請求的URL-Path(主機名和端口後面的URL部分),並將其添加到配置檔中指定的DocumentRoot
的末尾。因此,DocumentRoot
下麵的檔和目錄構成了可從Web上看到的基本文檔樹。
例如,如果DocumentRoot
設置為/var/www/html
時,則對http://www.example.com/fish/guppies.html
的請求會將檔/var/www/html/fish/guppies.html
發送到請求客戶。
如果請求目錄(即以/結尾的路徑),則從該目錄提供的檔由DirectoryIndex
指令定義。例如,如果DocumentRoot
設置為/var/www/html/
,則要設置:
DirectoryIndex index.html index.php
然後,對http://www.example.com/fish/
的請求將導致httpd嘗試提供檔/var/www/html/fish/index.html
。如果該檔不存在,它將接下來嘗試提供檔/var/www/html/fish/index.php
。
如果這兩個檔都不存在,則下一步是嘗試提供目錄索引,加載mod_autoindex
並配置為允許該目錄索引。
httpd還具有虛擬主機功能,伺服器可以接收多個主機的請求。在這種情況下,可以為每個虛擬主機指定不同的DocumentRoot
,或者,模組mod_vhost_alias
提供的指令可用於根據請求的IP地址或主機名動態確定從中提供內容的適當位置。
DocumentRoot之外的檔
通常情況下,必須允許Web訪問檔系統中嚴格不在DocumentRoot
下的部分。httpd提供了幾種不同的方法來實現這一目標。在Unix系統上,符號鏈接可以將檔系統的其他部分帶到DocumentRoot
下。出於安全原因,僅當相關目錄的Options
設置包括FollowSymLinks
或SymLinksIfOwnerMatch
時,httpd才會遵循符號鏈接。
或者,Alias指令將檔系統的任何部分映射到Web空間。例如,
Alias "/docs" "/var/web"
網址 http://www.example.com/docs/dir/file.html
將從/var/web/dir/file.html
提供。ScriptAlias
指令的工作方式相同,其附加效果是位於目標路徑的所有內容都被視為CGI腳本。
對於需要額外靈活性的情況,可以使用AliasMatch
和ScriptAliasMatch
指令來執行基於正則運算式的強大匹配和替換。例如,
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系統上,特定用戶的主目錄可以稱為~user/
。模組mod_userdir
通過允許使用以下URL訪問每個用戶主目錄下的檔,將此想法擴展到Web。
http://www.example.com/~user/file.html
出於安全原因,從Web直接訪問用戶的主目錄是不合適的。因此,UserDir
指令指定用戶主目錄下Web目錄所在的目錄。使用Userdir public_html
的默認設置,上面的URL映射到/home/user/public_html/file.html
等目錄中的檔,其中/home/user/
是/etc/passwd
中指定的用戶主目錄。
有些人發現~
符號(通常在網路上編碼為%7e
)很尷尬,並且更喜歡使用替代字串來表示用戶目錄。mod_userdir
不支持此功能。但是,如果用戶的主目錄以常規方式構造,則可以使用AliasMatch
指令來實現所需的效果。例如,要將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/$3"
URL重定向
上面討論的配置指令告訴httpd從檔系統中的特定位置獲取內容並將其返回給客戶端。有時,希望通知客戶端所請求的內容位於不同的URL,並指示客戶端使用新URL發出新請求。這稱為重定向,由Redirect
指令實現。例如,如果DocumentRoot
下目錄/foo/
的內容被移動到新目錄/bar/
,可以指示客戶端在新位置請求內容,如下所示:
Redirect permanent "/foo/" "http://www.example.com/bar/"
這會將從/foo/
開始的任何URL-Path重定向到www.example.com
伺服器上的相同URL路徑,其中/bar/
替換為/foo/
。可以將客戶端重定向到任何伺服器,而不僅僅是原始伺服器。
httpd還提供了RedirectMatch
指令,用於更複雜的重寫問題。例如,要將站點主頁的請求重定向到其他站點,但僅保留所有其他請求,請使用以下配置:
RedirectMatch permanent "^/$" "http://www.example.com/startpage.html"
或者,要臨時將一個站點上的所有頁面重定向到另一個站點上的特定頁面,請使用以下命令:
RedirectMatch temp ".*" "http://othersite.example.com/startpage.html"
反向代理
httpd還允許將遠程文檔帶入本地伺服器的URL空間。此技術稱為反向代理,因為Web伺服器通過從遠程伺服器獲取文檔並將其返回到客戶端來充當代理伺服器。它與正常(轉發)代理不同,因為對於客戶端,文檔似乎來自反向代理伺服器。
在以下示例中,當客戶端請求/foo/
目錄下的頁面文檔時,伺服器從internal.example.com
上的/bar/
目錄中獲取這些文檔,並將它們返回給客戶端,就像它們來自本地伺服器一樣。
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
配置伺服器以獲取相應的文檔,而ProxyPassReverse
指令重寫源自internal.example.com
的重定向,以便它們定位到本地伺服器上的相應目錄。同樣,ProxyPassReverseCookieDomain
和ProxyPassReverseCookiePath
重寫由後端伺服器設置的cookie。
但是,請務必注意,文檔中的鏈接不會被重寫。因此,internal.example.com
上的任何絕對鏈接都將導致客戶端突破代理伺服器並直接從internal.example.com
請求。您可以使用mod_substitute
在頁面中修改這些鏈接(以及其他內容)。
Substitute "s/internal\.example\.com/www.example.com/i"
對於HTML和XHTML中鏈接的更複雜重寫,mod_proxy_html
模組也可用。它允許創建需要重寫的URL映射,以便可以處理複雜的代理方案。
重寫引擎
當需要更強大的替換時,mod_rewrite
提供的重寫引擎可能很有用。該模組提供的指令可以使用請求的特徵(例如流覽器類型或源IP地址)來決定從哪里提供內容。此外,mod_rewrite
可以使用外部資料庫檔或程式來確定如何處理請求。重寫引擎能夠執行上面討論的所有三種類型的映射:內部重定向(別名),外部重定向和代理。
檔未找到
不可避免地請求有時也會在檔系統中找不到匹配檔的URL。這可能由於幾個原因而發生。在某些情況下,它可能是將文檔從一個位置移動到另一個位置的結果。在這種情況下,最好使用URL重定向來通知客戶端資源的新位置。通過這種方式,即使資源位於新位置,您也可以確保舊書簽和鏈接繼續有效。
“找不到檔”錯誤的另一個常見原因是URL的直接錯誤輸入,無論是直接在流覽器中還是在HTML鏈接中。httpd提供模組mod_speling(sic)
來幫助解決這個問題。啟動此模組時,它將攔截“找不到檔”錯誤並查找具有類似檔案名的資源。如果找到一個這樣的檔,mod_speling
將向客戶端發送HTTP重定向,通知它正確的位置。如果找到幾個“關閉”檔,將向客戶提供可用備選列表。
mod_speling
的一個特別有用的功能是,它將比較檔案名而不考慮大小寫。這可以幫助用戶不了解URL和unix檔系統的區分大小寫特性的系統。但是,除了偶爾的URL更正之外,使用mod_speling
可以在伺服器上增加額外負載,因為每個“不正確”的請求後面都有URL重定向和來自客戶端的新請求。
mod_dir
提供FallbackResource
,可用於將虛擬URI映射到真實資源,然後為其提供服務。在實現’前端控制器’時,這是對mod_rewrite
非常有用的替代品
如果查找內容的所有嘗試都失敗,httpd將返回一個錯誤頁面,其中包含HTTP狀態代碼404(找不到檔)。此頁面的外觀由ErrorDocument
指令控制,可以按照自定義錯誤回應文檔中的討論以靈活的方式進行自定義。