本文將介紹Apache HTTP Server如何使用請求的URL來確定從中提供檔案的檔案系統位置。
在決定為給定請求提供什麼檔案時,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地址或主機名動態確定從中提供內容的適當位置。
通常情況下,必須允許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"
上面討論的組態指令告訴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
指令控制,可以按照自定義錯誤響應文件中的討論以靈活的方式進行自定義。