1 定义ngx_http_core_post_rewrite_phase 函数 定义在 ./nginx-1.24.0/src/http/ngx_http_core_module.cngx_int_tngx_http_core_post_rewrite_phase(ngx_http_request_t*r,ngx_http_phase_handler_t*ph){ngx_http_core_srv_conf_t*cscf;ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,post rewrite phase: %ui,r-phase_handler);if(!r-uri_changed){r-phase_handler;returnNGX_AGAIN;}ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,uri changes: %d,r-uri_changes);/* * gcc before 3.3 compiles the broken code for * if (r-uri_changes-- 0) * if the r-uri_changes is defined as * unsigned uri_changes:4 */r-uri_changes--;if(r-uri_changes0){ngx_log_error(NGX_LOG_ERR,r-connection-log,0,rewrite or internal redirection cycle while processing \%V\,r-uri);ngx_http_finalize_request(r,NGX_HTTP_INTERNAL_SERVER_ERROR);returnNGX_OK;}r-phase_handlerph-next;cscfngx_http_get_module_srv_conf(r,ngx_http_core_module);r-loc_confcscf-ctx-loc_conf;returnNGX_AGAIN;}ngx_http_core_post_rewrite_phase 函数是 NGX_HTTP_POST_REWRITE_PHASE 阶段的检查器 核心作用可概括为 检查 URI 是否被 rewrite 阶段修改 - 若 未修改则正常推进到下一个阶段NGX_HTTP_PREACCESS_PHASE。 - 若 已修改则扣减重定向配额 检测是否发生重定向循环超过上限则返回 500 错误 然后将请求 跳转回 NGX_HTTP_FIND_CONFIG_PHASE 重新进行 location 匹配实现内部重定向。2 详解1 函数签名ngx_int_tngx_http_core_post_rewrite_phase(ngx_http_request_t*r,ngx_http_phase_handler_t*ph)返回值 用于返回函数执行结果的状态码 NGX_AGAIN 表示继续循环可能跳转阶段 NGX_OK 表示请求已终结引擎应退出。参数1 ngx_http_request_t *r 指向当前 HTTP 请求上下文结构体参数2 ngx_http_phase_handler_t *ph 指向 ngx_http_phase_handler_t 结构体的指针 代表当前在 阶段处理引擎 数组 中的处理器项2 逻辑流程1 未修改URI 2 修改过 URI 2-1 递减内部重定向计数器 2-2 重写死循环 2-3 跳转回 FIND_CONFIG 阶段 2-4 恢复 server 级别的 location 配置 2-5 返回 NGX_AGAIN1 未修改URI{ngx_http_core_srv_conf_t*cscf;ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,post rewrite phase: %ui,r-phase_handler);if(!r-uri_changed){r-phase_handler;returnNGX_AGAIN;}检查 URI 是否被修改 判断 rewrite 阶段是否修改了请求的 URI由 r-uri_changed 标志位指示 r-phase_handler 将索引递增 指向 NGX_HTTP_PREACCESS_PHASE 的起始处理器。 返回 NGX_AGAIN通知阶段引擎继续循环执行新索引对应的处理器。 这是大多数请求走的路径 表示 rewrite 规则没有改变 URI 请求可以直接进入后续的访问控制等阶段 无需重新匹配 location。2 修改过 URI2-1 递减内部重定向计数器ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,uri changes: %d,r-uri_changes);/* * gcc before 3.3 compiles the broken code for * if (r-uri_changes-- 0) * if the r-uri_changes is defined as * unsigned uri_changes:4 */r-uri_changes--;将请求的剩余内部重定向次数减 1 每次因为 URI 改变而准备跳回 NGX_HTTP_FIND_CONFIG_PHASE 时消耗一次配额。 这是防止无限循环的第一道防线。 意义为后续的死循环检测提供基础。2-2 重写死循环if(r-uri_changes0){ngx_log_error(NGX_LOG_ERR,r-connection-log,0,rewrite or internal redirection cycle while processing \%V\,r-uri);ngx_http_finalize_request(r,NGX_HTTP_INTERNAL_SERVER_ERROR);returnNGX_OK;}检测重定向/重写死循环 当 r-uri_changes 递减到 0 时 判定发生了 rewrite 或内部重定向死循环终止请求 记录一条错误日志明确指出当前 URI 导致了重定向循环。 调用 ngx_http_finalize_request以 HTTP 500 Internal Server Error 结束请求。 返回 NGX_OK 给阶段引擎通知引擎当前请求已终结应退出处理循环。 意义 保护服务器资源避免因配置错误 导致请求无限循环占用 worker 进程。2-3 跳转回 FIND_CONFIG 阶段r-phase_handlerph-next;跳转回 FIND_CONFIG 阶段 将请求的阶段处理器索引重置为 ph-next 所指示的值。 逻辑 在 Nginx 配置加载时当前 post-rewrite 阶段的处理器项的 next 字段被预设为 NGX_HTTP_FIND_CONFIG_PHASE 的起始索引。 这行代码等价于“跳转到 location 匹配阶段”。2-4 恢复 server 级别的 location 配置cscfngx_http_get_module_srv_conf(r,ngx_http_core_module);r-loc_confcscf-ctx-loc_conf;将请求的 location 配置r-loc_conf重置为当前虚拟主机的默认 location 配置。 逻辑 首先通过 ngx_http_get_module_srv_conf 获取 server 级别的 ngx_http_core_module 配置。 cscf-ctx-loc_conf 是一个指向该 server 默认 location 配置指针数组的指针。 将 r-loc_conf 指向这个默认配置 意味着请求暂时遗忘了之前匹配到的具体 location 后续的 FIND_CONFIG 阶段会基于新的 URI 重新进行完整的 location 匹配。 意义 确保内部重定向后的 location 匹配完全独立 不会受到上一轮已匹配 location 的配置影响 保证了配置逻辑的正确隔离。2-5 返回 NGX_AGAINreturnNGX_AGAIN;}返回 NGX_AGAIN 继续引擎循环 向阶段引擎返回 NGX_AGAIN
ngx_http_core_post_rewrite_phase
发布时间:2026/6/2 21:30:43
1 定义ngx_http_core_post_rewrite_phase 函数 定义在 ./nginx-1.24.0/src/http/ngx_http_core_module.cngx_int_tngx_http_core_post_rewrite_phase(ngx_http_request_t*r,ngx_http_phase_handler_t*ph){ngx_http_core_srv_conf_t*cscf;ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,post rewrite phase: %ui,r-phase_handler);if(!r-uri_changed){r-phase_handler;returnNGX_AGAIN;}ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,uri changes: %d,r-uri_changes);/* * gcc before 3.3 compiles the broken code for * if (r-uri_changes-- 0) * if the r-uri_changes is defined as * unsigned uri_changes:4 */r-uri_changes--;if(r-uri_changes0){ngx_log_error(NGX_LOG_ERR,r-connection-log,0,rewrite or internal redirection cycle while processing \%V\,r-uri);ngx_http_finalize_request(r,NGX_HTTP_INTERNAL_SERVER_ERROR);returnNGX_OK;}r-phase_handlerph-next;cscfngx_http_get_module_srv_conf(r,ngx_http_core_module);r-loc_confcscf-ctx-loc_conf;returnNGX_AGAIN;}ngx_http_core_post_rewrite_phase 函数是 NGX_HTTP_POST_REWRITE_PHASE 阶段的检查器 核心作用可概括为 检查 URI 是否被 rewrite 阶段修改 - 若 未修改则正常推进到下一个阶段NGX_HTTP_PREACCESS_PHASE。 - 若 已修改则扣减重定向配额 检测是否发生重定向循环超过上限则返回 500 错误 然后将请求 跳转回 NGX_HTTP_FIND_CONFIG_PHASE 重新进行 location 匹配实现内部重定向。2 详解1 函数签名ngx_int_tngx_http_core_post_rewrite_phase(ngx_http_request_t*r,ngx_http_phase_handler_t*ph)返回值 用于返回函数执行结果的状态码 NGX_AGAIN 表示继续循环可能跳转阶段 NGX_OK 表示请求已终结引擎应退出。参数1 ngx_http_request_t *r 指向当前 HTTP 请求上下文结构体参数2 ngx_http_phase_handler_t *ph 指向 ngx_http_phase_handler_t 结构体的指针 代表当前在 阶段处理引擎 数组 中的处理器项2 逻辑流程1 未修改URI 2 修改过 URI 2-1 递减内部重定向计数器 2-2 重写死循环 2-3 跳转回 FIND_CONFIG 阶段 2-4 恢复 server 级别的 location 配置 2-5 返回 NGX_AGAIN1 未修改URI{ngx_http_core_srv_conf_t*cscf;ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,post rewrite phase: %ui,r-phase_handler);if(!r-uri_changed){r-phase_handler;returnNGX_AGAIN;}检查 URI 是否被修改 判断 rewrite 阶段是否修改了请求的 URI由 r-uri_changed 标志位指示 r-phase_handler 将索引递增 指向 NGX_HTTP_PREACCESS_PHASE 的起始处理器。 返回 NGX_AGAIN通知阶段引擎继续循环执行新索引对应的处理器。 这是大多数请求走的路径 表示 rewrite 规则没有改变 URI 请求可以直接进入后续的访问控制等阶段 无需重新匹配 location。2 修改过 URI2-1 递减内部重定向计数器ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,uri changes: %d,r-uri_changes);/* * gcc before 3.3 compiles the broken code for * if (r-uri_changes-- 0) * if the r-uri_changes is defined as * unsigned uri_changes:4 */r-uri_changes--;将请求的剩余内部重定向次数减 1 每次因为 URI 改变而准备跳回 NGX_HTTP_FIND_CONFIG_PHASE 时消耗一次配额。 这是防止无限循环的第一道防线。 意义为后续的死循环检测提供基础。2-2 重写死循环if(r-uri_changes0){ngx_log_error(NGX_LOG_ERR,r-connection-log,0,rewrite or internal redirection cycle while processing \%V\,r-uri);ngx_http_finalize_request(r,NGX_HTTP_INTERNAL_SERVER_ERROR);returnNGX_OK;}检测重定向/重写死循环 当 r-uri_changes 递减到 0 时 判定发生了 rewrite 或内部重定向死循环终止请求 记录一条错误日志明确指出当前 URI 导致了重定向循环。 调用 ngx_http_finalize_request以 HTTP 500 Internal Server Error 结束请求。 返回 NGX_OK 给阶段引擎通知引擎当前请求已终结应退出处理循环。 意义 保护服务器资源避免因配置错误 导致请求无限循环占用 worker 进程。2-3 跳转回 FIND_CONFIG 阶段r-phase_handlerph-next;跳转回 FIND_CONFIG 阶段 将请求的阶段处理器索引重置为 ph-next 所指示的值。 逻辑 在 Nginx 配置加载时当前 post-rewrite 阶段的处理器项的 next 字段被预设为 NGX_HTTP_FIND_CONFIG_PHASE 的起始索引。 这行代码等价于“跳转到 location 匹配阶段”。2-4 恢复 server 级别的 location 配置cscfngx_http_get_module_srv_conf(r,ngx_http_core_module);r-loc_confcscf-ctx-loc_conf;将请求的 location 配置r-loc_conf重置为当前虚拟主机的默认 location 配置。 逻辑 首先通过 ngx_http_get_module_srv_conf 获取 server 级别的 ngx_http_core_module 配置。 cscf-ctx-loc_conf 是一个指向该 server 默认 location 配置指针数组的指针。 将 r-loc_conf 指向这个默认配置 意味着请求暂时遗忘了之前匹配到的具体 location 后续的 FIND_CONFIG 阶段会基于新的 URI 重新进行完整的 location 匹配。 意义 确保内部重定向后的 location 匹配完全独立 不会受到上一轮已匹配 location 的配置影响 保证了配置逻辑的正确隔离。2-5 返回 NGX_AGAINreturnNGX_AGAIN;}返回 NGX_AGAIN 继续引擎循环 向阶段引擎返回 NGX_AGAIN