src\http\ngx_http_core_module.c
ngx_int_t
ngx_http_core_content_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
{
size_t root;
ngx_int_t rc;
ngx_str_t path;
if (r->content_handler) {
r->write_event_handler = ngx_http_request_empty_handler;
ngx_http_finalize_request(r, r->content_handler(r));
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"content phase: %ui", r->phase_handler);
rc = ph->handler(r);
if (rc != NGX_DECLINED) {
ngx_http_finalize_request(r, rc);
return NGX_OK;
}
/* rc == NGX_DECLINED */
ph++;
if (ph->checker) {
r->phase_handler++;
return NGX_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);
return NGX_OK;
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
return NGX_OK;
}
ngx_http_core_content_phase 是 Nginx HTTP 核心模块中处理内容生成阶段(content phase)的关键函数。这个函数负责协调请求的内容生成过程,包括调用预定义的内容处理器(content handler)或按阶段顺序尝试不同的处理器。
函数签名
ngx_int_t
ngx_http_core_content_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
r: 当前 HTTP 请求对象,包含请求的所有相关信息ph: 当前阶段处理器对象,包含处理函数和检查器
变量声明
size_t root;
ngx_int_t rc;
ngx_str_t path;
root: 用于存储路径根目录的长度rc: 存储处理函数的返回码path: 用于存储映射后的文件路径
检查预定义的内容处理器
if (r->content_handler) {
r->write_event_handler = ngx_http_request_empty_handler;
ngx_http_finalize_request(r, r->content_handler(r));
return NGX_OK;
}
- 如果请求已经设置了
content_handler(通常在location配置中指定),则直接调用该处理器 - 设置写事件处理器为空处理器(
ngx_http_request_empty_handler) - 调用
ngx_http_finalize_request完成请求处理,传入内容处理器的返回值 - 返回
NGX_OK表示处理完成
调试日志
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"content phase: %ui", r->phase_handler);
- 记录调试日志,显示当前处于内容阶段,并输出阶段处理器索引
调用当前阶段处理器
rc = ph->handler(r);
- 调用当前阶段处理器(
ph->handler)处理请求 - 将返回值存储在
rc变量中
此时的 ph->handler 是
ngx_http_index_handler
处理非DECLINED返回值
if (rc != NGX_DECLINED) {
ngx_http_finalize_request(r, rc);
return NGX_OK;
}
- 如果处理器返回值不是
NGX_DECLINED(表示拒绝处理),则认为该处理器已经处理了请求 - 调用
ngx_http_finalize_request完成请求处理 - 返回
NGX_OK表示处理完成
处理DECLINED情况
/* rc == NGX_DECLINED */
ph++;
if (ph->checker) {
r->phase_handler++;
return NGX_AGAIN;
}
- 如果处理器返回
NGX_DECLINED,表示它拒绝处理当前请求 - 移动到下一个阶段处理器(
ph++) - 如果下一个处理器有效(有checker函数),则:
- 递增请求的阶段处理器索引(
r->phase_handler++) - 返回
NGX_AGAIN让核心循环继续尝试下一个处理器
- 递增请求的阶段处理器索引(
没有找到内容处理器的情况
处理目录请求(URI以/结尾)
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);
return NGX_OK;
}
- 如果URI以斜杠(/)结尾,表示这是一个目录请求
- 尝试将URI映射到文件系统路径(用于错误日志)
- 记录错误日志,显示目录索引被禁止
- 返回403 Forbidden状态码终止请求
处理一般未找到情况
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
return NGX_OK;
- 记录错误日志,表示没有找到合适的处理器
- 返回404 Not Found状态码终止请求
- 返回
NGX_OK表示处理完成
总结
ngx_http_core_content_phase 函数是Nginx内容生成阶段的核心调度器,它的主要逻辑流程是:
- 首先检查是否有预定义的内容处理器,有则直接调用
- 否则按阶段处理器数组顺序尝试各个处理器
- 如果处理器返回非DECLINED,则完成请求处理
- 如果处理器返回DECLINED,则尝试下一个处理器
- 如果所有处理器都拒绝处理,则根据URI类型返回403或404错误
这个函数体现了Nginx的高度模块化设计,通过阶段处理器机制,不同的模块可以注册自己的内容处理器,而核心模块负责协调这些处理器的执行顺序和结果处理。
754

被折叠的 条评论
为什么被折叠?



