Apache HTTP Server 版本 2.4
相关模块 | 相关指令 |
---|---|
在决定为给定请求提供哪个文件时,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
设置如上,并且您要设置
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
指令在您的主服务器配置文件 (httpd.conf
) 中设置,并且可能在您创建的每个附加 虚拟主机 中设置一次。
通常情况下,需要允许对不在 DocumentRoot
下面的文件系统的部分进行 Web 访问。httpd 提供了几种不同的方法来实现这一点。在 Unix 系统上,符号链接可以将文件系统的其他部分引入 DocumentRoot
下面。出于安全原因,httpd 仅在相关目录的 Options
设置包含 FollowSymLinks
或 SymLinksIfOwnerMatch
时才会遵循符号链接。
或者,Alias
指令将文件系统的任何部分映射到 Web 空间。例如,使用
Alias "/docs" "/var/web"
URL 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
将此想法扩展到 Web,允许访问每个用户主目录下的文件,使用以下 URL。
http://www.example.com/~user/file.html
出于安全原因,从 Web 直接访问用户主目录是不合适的。因此,UserDir
指令指定用户主目录下的一个目录,其中存放 Web 文件。使用 Userdir public_html
的默认设置,上面的 URL 映射到类似 /home/user/public_html/file.html
的目录下的文件,其中 /home/user/
是用户在 /etc/passwd
中指定的主目录。
还有几种其他形式的 Userdir
指令,您可以在 /etc/passwd
不包含主目录位置的系统上使用。
有些人发现“~”符号(通常在 Web 上编码为 %7e
)很笨拙,更喜欢使用替代字符串来表示用户目录。mod_userdir 不支持此功能。但是,如果用户的 home 目录以规律的方式构建,那么可以使用 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 可以使用外部数据库文件或程序来确定如何处理请求。重写引擎能够执行上面讨论的所有三种类型的映射:内部重定向(别名)、外部重定向和代理。在 详细的 mod_rewrite 文档 中讨论了许多使用 mod_rewrite 的实际示例。
不可避免地,会请求到文件系统中找不到匹配文件的 URL。这可能由于多种原因导致。在某些情况下,可能是由于将文档从一个位置移动到另一个位置。在这种情况下,最好使用 URL 重定向 来通知客户端资源的新位置。这样,即使资源位于新位置,您也可以确保旧书签和链接继续有效。
导致“文件未找到”错误的另一个常见原因是意外地错误输入 URL,无论是直接在浏览器中还是在 HTML 链接中。httpd 提供了模块 mod_speling
(原文如此)来帮助解决此问题。当此模块被激活时,它将拦截“文件未找到”错误并查找具有类似文件名的资源。如果找到一个这样的文件,mod_speling 将向客户端发送 HTTP 重定向,通知它正确的位置。如果找到多个“接近”的文件,则会向客户端呈现可用备选方案的列表。
mod_speling 的一个特别有用的功能是,它将比较文件名而不考虑大小写。这可以帮助用户不知道 URL 和 Unix 文件系统区分大小写的系统。但是,将 mod_speling 用于除偶尔的 URL 校正之外的任何用途都会给服务器带来额外的负载,因为每个“不正确”的请求都会随之进行 URL 重定向,以及来自客户端的新请求。
mod_dir
提供了 FallbackResource
,它可以用来将虚拟 URI 映射到一个真实的资源,然后由它来提供服务。在实现“前端控制器”时,这是一个非常有用的 mod_rewrite
的替代方案。
如果所有定位内容的尝试都失败,httpd 将返回一个带有 HTTP 状态码 404(文件未找到)的错误页面。此页面的外观由 ErrorDocument
指令控制,并且可以像 自定义错误响应 文档中所述那样以灵活的方式进行自定义。
其他可用于 URL 映射的模块包括
mod_actions
- 根据请求方法或资源 MIME 类型将请求映射到 CGI 脚本。mod_dir
- 提供将尾部斜杠基本映射到索引文件(如 index.html
)的功能。mod_imagemap
- 根据用户在 HTML 文档中嵌入的图像上点击的位置,将请求映射到 URL。mod_negotiation
- 根据客户端的偏好(如语言或内容压缩)选择合适的文档。