ngx_http_init_phases

张开发
2026/4/17 8:20:15 15 分钟阅读

分享文章

ngx_http_init_phases
1 定义ngx_http_init_phases 函数 定义在 ./nginx-1.24.0/src/http/ngx_http.cstaticngx_int_tngx_http_init_phases(ngx_conf_t*cf,ngx_http_core_main_conf_t*cmcf){if(ngx_array_init(cmcf-phases[NGX_HTTP_POST_READ_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}if(ngx_array_init(cmcf-phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}if(ngx_array_init(cmcf-phases[NGX_HTTP_REWRITE_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}if(ngx_array_init(cmcf-phases[NGX_HTTP_PREACCESS_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}if(ngx_array_init(cmcf-phases[NGX_HTTP_ACCESS_PHASE].handlers,cf-pool,2,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}if(ngx_array_init(cmcf-phases[NGX_HTTP_PRECONTENT_PHASE].handlers,cf-pool,2,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}if(ngx_array_init(cmcf-phases[NGX_HTTP_CONTENT_PHASE].handlers,cf-pool,4,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}if(ngx_array_init(cmcf-phases[NGX_HTTP_LOG_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}returnNGX_OK;}ngx_http_init_phases 函数的作用是 初始化 HTTP 请求处理各个阶段Phases的处理函数数组。2 详解1 函数签名static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)返回值 NGX_OK (0)初始化成功。 NGX_ERROR (-1)初始化失败参数 ngx_conf_t *cf 指向当前配置解析上下文 ngx_http_core_main_conf_t *cmcf HTTP 核心模块的主配置结构体指针。 它存储了 HTTP 核心层面的配置信息其中 cmcf-phases 是存储所有处理阶段信息的数组。2 逻辑流程1 初始化 NGX_HTTP_POST_READ_PHASE 请求处理阶段的处理函数数组 2 初始化 NGX_HTTP_SERVER_REWRITE_PHASE 请求处理阶段的处理函数数组 3 初始化 NGX_HTTP_REWRITE_PHASE 请求处理阶段的处理函数数组 4 初始化 NGX_HTTP_PREACCESS_PHASE 请求处理阶段的处理函数数组 5 初始化 NGX_HTTP_ACCESS_PHASE 请求处理阶段的处理函数数组 6 初始化 NGX_HTTP_PRECONTENT_PHASE 请求处理阶段的处理函数数组 7 初始化 NGX_HTTP_CONTENT_PHASE 请求处理阶段的处理函数数组 8 初始化 NGX_HTTP_LOG_PHASE 请求处理阶段的处理函数数组 9 返回成功1 初始化 NGX_HTTP_POST_READ_PHASE 请求处理阶段的处理函数数组{if(ngx_array_init(cmcf-phases[NGX_HTTP_POST_READ_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}cmcf指向 ngx_http_core_main_conf_t 结构体 这是 HTTP 核心模块的主配置存储了所有全局性的 HTTP 配置信息。 phases是 cmcf 中的一个数组包含了 HTTP 请求处理的所有阶段共 11 个阶段。 NGX_HTTP_POST_READ_PHASE 这是一个枚举常量通常值为 0代表 “读取请求头之后” 的阶段。 这是请求处理流水线的第一个可干预阶段。 .handlers每个阶段结构体中都有一个 handlers 成员类型是 ngx_array_t动态数组。 这个数组用来存储该阶段所有已注册的回调函数指针。 cmcf-phases 是一个结构体数组数组元素代表请求处理阶段。 每个阶段结构体内部包含一个动态数组 (ngx_array_t)用来存储该阶段需要执行的处理函数指针。 当前代码正在初始化第一个阶段 (NGX_HTTP_POST_READ_PHASE) 的这个动态数组 预分配了 1 个元素的空间每个元素的大小是 ngx_http_handler_pt函数指针。2 初始化 NGX_HTTP_SERVER_REWRITE_PHASE请求处理阶段的处理函数数组if(ngx_array_init(cmcf-phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}第二个请求处理阶段 NGX_HTTP_SERVER_REWRITE_PHASE 的处理函数数组的初始化 NGX_HTTP_POST_READ_PHASE 代表 刚读完请求头还没做任何处理 NGX_HTTP_SERVER_REWRITE_PHASE 代表 在后读取之后匹配 location 之前 主要用于在 server 级别对请求 URI 进行重写例如通过 rewrite 指令3 初始化 NGX_HTTP_REWRITE_PHASE 请求处理阶段的处理函数数组if(ngx_array_init(cmcf-phases[NGX_HTTP_REWRITE_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}第4个请求处理阶段 NGX_HTTP_REWRITE_PHASE 的处理函数数组的初始化NGX_HTTP_REWRITE_PHASE 代表的是 HTTP 请求处理流程中的Location 级别重写阶段 执行时机在 Location 匹配之后 这是它与 SERVER_REWRITE_PHASE 最大的区别虽然在这段初始化代码中它是第 3 个 但在 Nginx 定义的所有枚举阶段中它实际上是第 4 个 枚举顺序 1. NGX_HTTP_POST_READ_PHASE (索引 0) 2. NGX_HTTP_SERVER_REWRITE_PHASE (索引 1) 3. NGX_HTTP_FIND_CONFIG_PHASE (索引 2) **注意这里** 4. NGX_HTTP_REWRITE_PHASE (索引 3) 为什么代码里跳过了 FIND_CONFIG_PHASE NGX_HTTP_FIND_CONFIG_PHASE 是一个内部控制阶段 它的核心任务是根据 URI 查找匹配的 location 配置。 这个过程由 Nginx 核心代码直接硬编码处理不允许第三方模块注册处理函数handlers 因此在 ngx_http_init_phases 函数中没有为它初始化 handlers 数组。4 初始化 NGX_HTTP_PREACCESS_PHASE 请求处理阶段的处理函数数组if(ngx_array_init(cmcf-phases[NGX_HTTP_PREACCESS_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}请求处理阶段 NGX_HTTP_PREACCESS_PHASE 的处理函数数组的初始化 NGX_HTTP_PREACCESS_PHASE 是 Nginx HTTP 请求处理流程中的预访问阶段 它的主要作用是 进行访问控制前的检查 在该阶段模块可以对请求进行一些与访问控制相关但又不属于严格认证/授权的预处理 例如 - 限制并发连接数limit_conn 模块 - 限制请求速率limit_req 模块 - 其他需要提前拦截的检查通常这些检查不涉及用户身份认证而是基于 IP、连接数或请求频率等条件。 - 与 ACCESS 阶段的区别 - PREACCESS 阶段通常用于资源层面的限流 - 检查是否超过连接数或请求速率如果超出则直接拒绝请求返回 503 等。 - ACCESS 阶段则用于用户身份认证和授权如 auth_basic、auth_request 以及 allow/deny返回 401/403 等。 - 执行顺序PREACCESS 先于 ACCESS 执行这样可以在认证之前就拦截掉明显超限的请求减轻后端认证模块的压力。 该阶段允许 Nginx 通过模块机制灵活扩展实现各种前置限流和安全检查。5 初始化 NGX_HTTP_ACCESS_PHASE 请求处理阶段的处理函数数组if(ngx_array_init(cmcf-phases[NGX_HTTP_ACCESS_PHASE].handlers,cf-pool,2,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}NGX_HTTP_ACCESS_PHASE 阶段的核心作用是 “访问控制与权限验证”。 它是 Nginx 请求处理流水线中的 “保安” 阶段负责决定请求是否有权限访问资源 执行时机预访问之后内容生成之前 在预访问之后确保限流等保护措施已经执行恶意请求已被拦截。 在内容生成之前确保在消耗资源生成响应内容之前先确认用户有权限访问。6 初始化 NGX_HTTP_PRECONTENT_PHASE 请求处理阶段的处理函数数组if(ngx_array_init(cmcf-phases[NGX_HTTP_PRECONTENT_PHASE].handlers,cf-pool,2,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}NGX_HTTP_PRECONTENT_PHASE 阶段的核心作用是 “内容生成前的预处理和准备”。 确定最终处理的内容 在该阶段Nginx 根据配置决定实际要处理的资源或动作但尚未开始生成响应体。 典型应用 ngx_http_try_files_module实现 try_files 指令依次检查文件是否存在 并选择对应的处理方式如返回文件、内部重定向等。 其他需要“预备”内容处理逻辑的模块。 与 CONTENT_PHASE 的区别 PRECONTENT 阶段关注“用什么内容”例如是静态文件还是内部 URI但不生成响应。 CONTENT 阶段负责实际生成响应体如输出文件、调用代理、返回 CGI 等。 执行特点该阶段的处理器通常不会直接发送响应 而是修改请求的配置如设置 content_handler 或进行内部重定向 让后续的 CONTENT 阶段执行具体工作。 执行时机访问控制之后内容生成之前 在访问控制之后确保用户已有权限访问才值得为内容生成做准备。 在内容生成之前确保在真正消耗资源生成内容之前完成所有必要的准备工作。 为什么要单独设这个阶段? 逻辑分离 将准备内容和生成内容分离职责更清晰7 初始化 NGX_HTTP_CONTENT_PHASE 请求处理阶段的处理函数数组if(ngx_array_init(cmcf-phases[NGX_HTTP_CONTENT_PHASE].handlers,cf-pool,4,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}NGX_HTTP_CONTENT_PHASE 阶段的核心作用是 “实际生成响应内容”。8 初始化 NGX_HTTP_LOG_PHASE 请求处理阶段的处理函数数组if(ngx_array_init(cmcf-phases[NGX_HTTP_LOG_PHASE].handlers,cf-pool,1,sizeof(ngx_http_handler_pt))!NGX_OK){returnNGX_ERROR;}NGX_HTTP_LOG_PHASE 阶段的核心作用是 “记录访问日志”9 返回成功returnNGX_OK;}请求处理阶段的定义typedefenum{NGX_HTTP_POST_READ_PHASE0,NGX_HTTP_SERVER_REWRITE_PHASE,NGX_HTTP_FIND_CONFIG_PHASE,NGX_HTTP_REWRITE_PHASE,NGX_HTTP_POST_REWRITE_PHASE,NGX_HTTP_PREACCESS_PHASE,NGX_HTTP_ACCESS_PHASE,NGX_HTTP_POST_ACCESS_PHASE,NGX_HTTP_PRECONTENT_PHASE,NGX_HTTP_CONTENT_PHASE,NGX_HTTP_LOG_PHASE}ngx_http_phases;不初始化的 3 个阶段 NGX_HTTP_FIND_CONFIG_PHASE (索引 2) NGX_HTTP_POST_REWRITE_PHASE (索引 4) NGX_HTTP_POST_ACCESS_PHASE (索引 7) 原因 这 3 个阶段是 Nginx 核心内部控制阶段。 它们的逻辑由 Nginx 核心代码硬编码实现不允许第三方模块注册处理函数。 因此不需要 handlers 数组来存储模块回调函数。 FIND_CONFIG 根据 URI 查找匹配的 location 这是路由核心逻辑必须由核心统一处理 POST_REWRITE 处理 rewrite last 后的内部跳转 跳转逻辑由核心控制模块不应干预 POST_ACCESS 访问检查后的汇总处理 需要统一判断所有 access handler 的结果HTTP 请求处理完整流程图 请求到达 │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 1. NGX_HTTP_POST_READ_PHASE │ │ (读取请求头后模块可干预) │ │ ✅ handlers 可注册 (如set_real_ip) │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 2. NGX_HTTP_SERVER_REWRITE_PHASE │ │ (server 级别 URL 重写) │ │ ✅ handlers 可注册 (如server 块 rewrite) │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 3. NGX_HTTP_FIND_CONFIG_PHASE │ │ (查找匹配的 location) │ │ ❌ 核心内部处理不可注册 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 4. NGX_HTTP_REWRITE_PHASE │ │ (location 级别 URL 重写) │ │ ✅ handlers 可注册 (如location 块 rewrite) │ │ ⚠️ 使用 last 标志会跳回 FIND_CONFIG 重新匹配 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 5. NGX_HTTP_POST_REWRITE_PHASE │ │ (重写后处理内部跳转) │ │ ❌ 核心内部处理不可注册 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 6. NGX_HTTP_PREACCESS_PHASE │ │ (访问控制前如限流) │ │ ✅ handlers 可注册 (如limit_req, limit_conn) │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 7. NGX_HTTP_ACCESS_PHASE │ │ (权限验证) │ │ ✅ handlers 可注册 (如auth_basic, allow/deny) │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 8. NGX_HTTP_POST_ACCESS_PHASE │ │ (访问检查后汇总) │ │ ❌ 核心内部处理不可注册 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 9. NGX_HTTP_PRECONTENT_PHASE │ │ (内容生成前预处理) │ │ ✅ handlers 可注册 (如try_files) │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 10. NGX_HTTP_CONTENT_PHASE │ │ (生成响应内容) │ │ ✅ handlers 可注册 (如static, proxy, fastcgi) │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 11. NGX_HTTP_LOG_PHASE │ │ (记录访问日志) │ │ ✅ handlers 可注册 (如access_log) │ └─────────────────────────────────────────────────────────────┘ │ ▼ 请求结束

更多文章