1 定义ngx_http_core_content_phase 函数 定义在 ./nginx-1.24.0/src/http/ngx_http_core_module.cngx_int_tngx_http_core_content_phase(ngx_http_request_t*r,ngx_http_phase_handler_t*ph){size_troot;ngx_int_trc;ngx_str_tpath;if(r-content_handler){r-write_event_handlerngx_http_request_empty_handler;ngx_http_finalize_request(r,r-content_handler(r));returnNGX_OK;}ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,content phase: %ui,r-phase_handler);rcph-handler(r);if(rc!NGX_DECLINED){ngx_http_finalize_request(r,rc);returnNGX_OK;}/* rc NGX_DECLINED */ph;if(ph-checker){r-phase_handler;returnNGX_AGAIN;}/* no content handler was found */if(r-uri.data[r-uri.len-1]/){if(ngx_http_map_uri_to_path(r,path,root,0)!NULL){ngx_log_error(NGX_LOG_ERR,r-connection-log,0,directory index of \%s\ is forbidden,path.data);}ngx_http_finalize_request(r,NGX_HTTP_FORBIDDEN);returnNGX_OK;}ngx_log_error(NGX_LOG_ERR,r-connection-log,0,no handler found);ngx_http_finalize_request(r,NGX_HTTP_NOT_FOUND);returnNGX_OK;}ngx_http_core_content_phase 函数是 NGX_HTTP_CONTENT_PHASE 阶段的检查器 负责 调度内容生成逻辑。 它会优先调用通过 r-content_handler 指定的内容处理器 否则依次尝试当前阶段注册的模块处理函数 直到某个模块成功处理请求 或所有模块均不处理时根据 URI 特征返回 403目录禁止或 404未找到。2 详解1 函数签名ngx_int_tngx_http_core_content_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 指向当前在阶段引擎数组中的处理器项2 逻辑流程1 局部变量 2 优先外部内容处理器 3 当前内容模块处理器 4 根据返回值处理 4-1 已处理 4-2 未处理 4-2-1 下一个 4-2-2 没有下一个 4-2-2-1 目录请求 4-2-2-2 非目录请求1 局部变量{size_troot;ngx_int_trc;ngx_str_tpath;2 优先外部内容处理器if(r-content_handler){r-write_event_handlerngx_http_request_empty_handler;ngx_http_finalize_request(r,r-content_handler(r));returnNGX_OK;}优先外部内容处理器 检查请求结构体中是否已存在一个预设的内容处理器。 逻辑 r-content_handler 可能由某些模块在前期阶段设置 表示该请求已明确由某个特定函数生成内容将写事件处理器重置为一个空操作函数。 逻辑 防止在最终化请求期间如果有写事件被触发 错误地调用了原来的写事件处理器可能再次进入内容阶段导致重复处理或异常。调用外部内容处理器生成响应然后立即最终化请求。 逻辑 r-content_handler(r) 执行实际的内容生成逻辑 其返回值作为参数传给 ngx_http_finalize_request 该函数负责发送响应头、响应体并清理请求。 意义将内容生成和请求收尾组合成一步高效且不易出错。返回 NGX_OK 给阶段引擎。 通知引擎当前请求已经最终化 应退出阶段循环不再执行后续阶段。ngx_log_debug1(NGX_LOG_DEBUG_HTTP,r-connection-log,0,content phase: %ui,r-phase_handler);3 当前内容模块处理器rcph-handler(r);调用当前内容模块处理器 执行当前阶段处理器项中注册的模块处理函数。 ph-handler 指向某个内容模块的函数 该函数尝试根据请求 URI 生成响应返回状态码。4 根据返回值处理4-1 已处理if(rc!NGX_DECLINED){ngx_http_finalize_request(r,rc);returnNGX_OK;}判断处理器是否处理了请求 检查模块返回值是否不是 NGX_DECLINED。 NGX_DECLINED 表示模块未处理此请求如静态文件不存在、不是自己的责任等。 任何其他返回值NGX_OK、错误码、HTTP 状态码都意味着模块已经“处理”了请求 无论成功还是失败。 意义这是责任链模式的关键判断一旦某个模块接管了请求整个内容阶段就应结束。4-2 未处理4-2-1 下一个/* rc NGX_DECLINED */ph;if(ph-checker){r-phase_handler;returnNGX_AGAIN;}当前处理器未处理尝试下一个 将 ph 指针后移指向引擎数组中的下一个处理器项。 因为当前模块拒绝了请求所以要检查是否还有其他内容模块可供尝试。检查下一个处理器项的 checker 是否非空。 若 checker 不为 NULL说明该处理器项有效 可能仍是内容阶段的处理器或者已进入下一阶段。 意义确认存在后续处理器避免越界。将请求的阶段处理器索引递增 1指向下一个处理器 返回 NGX_AGAIN 通知引擎继续循环 引擎收到该值后不会退出 而是用新的 r-phase_handler 继续执行 从而尝试下一个内容处理器。 实现内容处理器的链式尝试4-2-2 没有下一个4-2-2-1 目录请求/* no content handler was found */if(r-uri.data[r-uri.len-1]/){if(ngx_http_map_uri_to_path(r,path,root,0)!NULL){ngx_log_error(NGX_LOG_ERR,r-connection-log,0,directory index of \%s\ is forbidden,path.data);}ngx_http_finalize_request(r,NGX_HTTP_FORBIDDEN);returnNGX_OK;}检查请求 URI 的最后一个字符是否为 /即是否为目录请求 目录请求通常意味着期望一个默认索引文件如 index.html或目录列表。 如果没有内容处理器愿意处理它通常是因为索引文件不存在且目录列表被禁止。尝试将 URI 映射为实际文件系统路径 记录错误日志说明该目录的索引被禁止以 403 Forbidden 状态码最终化请求。 对于目录请求且无内容处理器 返回 403 是一种安全措施避免暴露目录结构。4-2-2-2 非目录请求ngx_log_error(NGX_LOG_ERR,r-connection-log,0,no handler found);ngx_http_finalize_request(r,NGX_HTTP_NOT_FOUND);returnNGX_OK;}非目录请求完全未找到处理器 记录错误日志明确表示找不到任何内容处理器 以 404 Not Found 状态码最终化请求
网站建设
高端定制
企业官网