apache请求处理采用8阶段模型:post_read_request、uri_translation、map_to_storage、header_parse、access_checker、check_user_id、auth_checker及fixups/response/logging/cleanup;各阶段严格串行,通过hook机制允许模块按需介入,request_rec结构体全程承载状态。

Apache 处理一个 HTTP 请求,不是线性执行的一条指令流,而是被拆解为多个职责明确、顺序固定的逻辑阶段;每个阶段通过 Hook 机制开放接口,允许模块按需介入。理解这组阶段与 Hook 的配合方式,就掌握了 Apache 可插拔、可配置、可审计的核心能力。
8 个核心请求处理阶段
Apache 官方源码与主流文档支持最细粒度的 8 阶段模型,各阶段严格串行,不可跳过或重排:
-
post_read_request:请求头刚解析完、
request_rec初步构建完成,但 URI 尚未解码、路径未映射。适合做协议升级(如强制 HTTPS)、原始请求篡改、基础安全拦截。 -
uri_translation:对 URI 进行解码、路径规范化,并应用
Alias、Redirect、RewriteRule等指令。结果是填充r->filename或标记为代理请求(如proxy:http://...)。 -
map_to_storage:确认资源最终归属——是磁盘文件、CGI 脚本、PHP 处理器,还是反向代理目标。此阶段触发
Require和Options类权限检查的实际评估。 -
header_parse:解析并标准化请求头字段(Host、Accept、Authorization 等),合并重复头、提取凭据、设置环境变量(
mod_setenvif在此生效)。 -
access_checker:执行基于 IP、域名、连接状态等的访问控制(
Require ip 192.168.1.0/24、Require host example.com)。 -
check_user_id:提取用户身份标识,如从
Authorization头中解析 Basic 或 Digest 凭据,或从 cookie/session 中还原用户上下文。 -
auth_checker:校验用户身份有效性与资源访问权限(如
Require user alice或Require group editors)。 -
fixups / response / logging / cleanup:收尾阶段集合。包括响应头微调(
mod_headers)、内容生成(mod_php或 default-handler)、日志记录(mod_log_config)、资源释放。
Hook 机制:模块如何“插入”流程
Hook 不是回调函数的简单注册,而是 Apache 实现模块可扩展性的底层契约:
- 每个阶段对应一个 Hook 名称(如
ap_hook_post_read_request),模块通过宏调用在启动时声明自己想参与哪个阶段。 - 所有挂载到同一 Hook 的函数,组成一个优先级有序的函数指针数组(
apr_array_header_t),由 Apache 运行时按序调用。 - 模块无需修改核心代码,只需实现函数并调用对应
ap_hook_XXX宏,即可在指定阶段介入;新增 Hook 也只需扩展该模块自身,不影响其他模块。 - 典型例子:
mod_ssl在post_read_request钩子中检查是否需升级连接;mod_rewrite在uri_translation钩子中执行规则匹配与重写。
request_rec:贯穿全程的状态载体
整个请求生命周期中,request_rec 结构体是唯一且共享的状态容器,它携带了所有关键字段:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
-
r->uri和r->unparsed_uri:原始与初步解析后的 URI; -
r->filename:经uri_translation和map_to_storage后确定的本地路径或代理标识; -
r->handler:最终选定的内容处理器(如php-script、cgi-script、default-handler); -
r->user、r->auth_type、r->notes等:用于跨阶段传递认证结果、临时数据或调试信息。
模块间不依赖全局变量,而是通过读写 request_rec 字段实现协作与状态延续。
配置继承与阶段生效时机
Apache 配置(<directory></directory>、<location></location>、<virtualhost></virtualhost>)并非在请求开始时一次性加载,而是按阶段动态合并:
-
uri_translation阶段前,仅能访问服务器级和虚拟主机级配置; -
uri_translation完成后,r->filename确定,Apache 才能匹配到具体目录或位置块,此时<directory></directory>中的Require才真正生效; - 这意味着
Require放在<location></location>块中,只在access_checker阶段起作用,且其作用范围由 URI 匹配决定,而非文件系统路径。
这种“延迟绑定”设计让配置更灵活,但也要求管理员清楚各指令实际生效的阶段与上下文。










