On this page
Apache HTTP Server 2.x 中的请求处理
Warning
警告-这是第一(快速)草案,需要进一步修订!
2.0 及更高版本中的一些更改会影响内部请求处理机制。模块作者需要了解这些更改,以便他们可以利用这些优化和安全性增强功能。
第一个主要变化是子请求和重定向机制。 Apache HTTP Server 1.3 中有许多不同的代码路径,以尝试优化子请求或重定向行为。在 2.0 版中引入补丁程序后,由于代码重复,这些优化(以及服务器行为)迅速遭到破坏。所有重复的代码都已折回到ap_process_request_internal()
,以防止代码再次不同步。
这意味着现有的许多代码都是“未优化的”。创建一个可靠且正确的 HTTP 服务器 RFC 实现是 Apache HTTP 项目的第一个目标。其他目标包括安全性,可伸缩性和优化。寻求了新的方法来优化服务器(超过 1.3 的性能),而又不引入脆弱或不安全的代码。
请求处理周期
所有请求都通过server/request.c
中的ap_process_request_internal()
传递,包括子请求和重定向。如果某个模块未通过此代码传递生成的请求,则警告作者,该模块可能会因将来对请求处理的更改而被破坏。
为了简化请求,模块作者可以利用hooks offered提早退出请求周期,或者绕过无关紧要的核心钩子(对于 CPU 而言代价很高)。
请求解析阶段
取消转义网址
在内部请求处理开始时,一次且仅一次取消转义请求的parsed_uri
路径。
如果设置了 proxyreq 标志,或者未设置parsed_uri.path
元素,则跳过此步骤。该模块无法对此单次转义操作进行进一步的控制,否则,如果无法转义或多次对 URL 进行转义会导致安全后果。
从 URI 中剥离“父级”和“此元素”
ap_getparents()
以及所有尾随的/.
或/..
元素都将删除所有/../
和/./
元素。这有助于确保在请求处理 continue 之前(几乎)绝对路径。 (有关更多讨论,请参见 RFC 1808 第 4 节.)
无法跳过此步骤。
初始 URI 位置漫游
每个请求都受到ap_location_walk()
调用。这样可以确保对所有请求都统一执行<Location>节。如果请求是内部重定向或子请求,则它可以从先前或父请求的 ap_location_walk 借用部分或全部处理,因此在处理主请求之后,此步骤通常非常有效。
translate_name
模块可以确定文件名,或在此步骤中更改给定的 URI。例如,mod_vhost_alias将 URI 的路径转换为已配置的虚拟主机,mod_alias会将路径转换为别名路径,并且如果请求退回到核心,则DocumentRoot会附加到请求资源中。
如果在此阶段所有模块DECLINE
,则将错误 500 返回到浏览器,并自动记录“无法翻译名称”错误。
Hook: map_to_storage
确定文件或正确的 URI 之后,将适当的每个目录配置合并在一起。例如,mod_proxy比较并合并适当的<Proxy>部分。如果 URI 只不过是本地(非代理)TRACE
请求,则核心将处理该请求并返回DONE
。如果没有模块用OK
或DONE
回答该钩子,则内核将针对<Directory>和<Files>节运行请求文件名。如果请求的“文件名”不是绝对的合法文件名,则会设置 Comments 以供以后终止。
URI 位置步行
第二个ap_location_walk()
调用强化了每个请求。这样可以确保翻译后的请求仍受配置的<Location>部分的约束。该请求再次从其先前的location_walk
借用了部分或全部处理,因此,除非转换后的 URI Map 到实质上不同的路径或虚拟主机,否则该步骤几乎总是非常高效。
Hook: header_parser
然后,主请求解析 Client 端的 Headers。这将准备其余的请求处理步骤,以更好地服务于 Client 的请求。
安全阶段
需要文档。代码是:
if ((access_status = ap_run_access_checker(r)) != 0) {
return decl_die(access_status, "check access", r);
}
if ((access_status = ap_run_check_user_id(r)) != 0) {
return decl_die(access_status, "check user", r);
}
if ((access_status = ap_run_auth_checker(r)) != 0) {
return decl_die(access_status, "check authorization", r);
}
准备阶段
Hook: type_checker
模块有机会根据目标资源测试 URI 或文件名,并为请求设置 mime 信息。 mod_mime和mod_mime_magic都使用此阶段来将文件名或内容与 Management 员的配置进行比较,并设置 Content Type,语言,字符集和请求处理程序。某些模块此时可能会设置其过滤器或其他请求处理参数。
如果在此阶段所有模块DECLINE
,则将错误 500 返回到浏览器,并自动记录“找不到类型”错误。
Hook: fixups
在上面的某个阶段,许多模块被“删节了”。模块使用修正阶段来“重新声明”其所有权或将请求的字段强制为适当的值。它并不总是最干净的机制,但有时是唯一的选择。
处理程序阶段
此阶段不是ap_process_request_internal()
处理的一部分。许多模块在创建任何内容之前都会准备一个或多个子请求。在核心或模块调用ap_process_request_internal()
之后,它随后调用ap_invoke_handler()
生成请求。
Hook: insert_filter
以某种方式转换内容的模块可以插入其值并覆盖现有过滤器,这样,如果用户无序配置了更高级的过滤器,则该模块可以根据需要移动其 Sequences。没有结果代码,因此最好信任此钩子中的操作以始终成功。
Hook: handler
该模块最终有机会在其处理程序钩子中处理该请求。请注意,并非每个准备好的请求都发送到处理程序钩子。许多模块(例如mod_autoindex)将为给定的 URI 创建子请求,然后不再提供该子请求,而只是为用户列出该子请求。切记不要将所需的拆卸操作从上面的钩子中放到该模块中,而应在请求池中注册池清理,以根据需要释放资源。