ngx_http_core_merge_srv_conf

时间:2025-03-30 09:53:30

定义在 src\http\ngx_http_core_module.c

static char *
ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_core_srv_conf_t *prev = parent;
    ngx_http_core_srv_conf_t *conf = child;

    ngx_str_t                name;
    ngx_http_server_name_t  *sn;

    /* TODO: it does not merge, it inits only */

    ngx_conf_merge_size_value(conf->connection_pool_size,
                              prev->connection_pool_size, 64 * sizeof(void *));
    ngx_conf_merge_size_value(conf->request_pool_size,
                              prev->request_pool_size, 4096);
    ngx_conf_merge_msec_value(conf->client_header_timeout,
                              prev->client_header_timeout, 60000);
    ngx_conf_merge_size_value(conf->client_header_buffer_size,
                              prev->client_header_buffer_size, 1024);
    ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
                              prev->large_client_header_buffers,
                              4, 8192);

    if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "the \"large_client_header_buffers\" size must be "
                           "equal to or greater than \"connection_pool_size\"");
        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_value(conf->ignore_invalid_headers,
                              prev->ignore_invalid_headers, 1);

    ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);

    ngx_conf_merge_value(conf->underscores_in_headers,
                              prev->underscores_in_headers, 0);

    if (conf->server_names.nelts == 0) {
        /* the array has 4 empty preallocated elements, so push cannot fail */
        sn = ngx_array_push(&conf->server_names);
#if (NGX_PCRE)
        sn->regex = NULL;
#endif
        sn->server = conf;
        ngx_str_set(&sn->name, "");
    }

    sn = conf->server_names.elts;
    name = sn[0].name;

#if (NGX_PCRE)
    if (sn->regex) {
        name.len++;
        name.data--;
    } else
#endif

    if (name.data[0] == '.') {
        name.len--;
        name.data++;
    }

    conf->server_name.len = name.len;
    conf->server_name.data = ngx_pstrdup(cf->pool, &name);
    if (conf->server_name.data == NULL) {
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}

函数作用

合并 HTTP 核心模块的父级配置 parent,通常来自 http 块)和子级配置 child,通常来自 server 块),处理默认值、约束条件和 server_name 的规范化。


ngx_http_core_srv_conf_t *prev = parent;
ngx_http_core_srv_conf_t *conf = child;
ngx_str_t name;
ngx_http_server_name_t *sn;
  • prevconf 分别指向父级和子级的配置结构体。
  • name 用于临时存储处理后的 server_name
  • sn 是指向 server_names 数组元素的指针。

ngx_conf_merge_size_value(conf->connection_pool_size, prev->connection_pool_size, 64 * sizeof(void *));
  • 作用 :合并 connection_pool_size(连接内存池大小)。
  • 逻辑 :如果子配置未设置,继承父配置;若父配置也未设置,使用默认值 64 * sizeof(void *)
  • 意义 :确保每个连接的内存池大小合理,避免内存浪费或不足。

ngx_conf_merge_size_value-****博客

conf->connection_pool_size=-1
prev->connection_pool_size=-1

执行后

conf->connection_pool_size=512


ngx_conf_merge_size_value(conf->request_pool_size, prev->request_pool_size, 4096);
  • 作用 :合并 request_pool_size(请求内存池大小)
  • 默认值 :4096

conf->request_pool_size=-1
prev->request_pool_size=-1

执行后

conf->request_pool_size=4096
 


ngx_conf_merge_msec_value(conf->client_header_timeout, prev->client_header_timeout, 60000);
  • 作用 :合并 client_header_timeout(客户端头超时时间)
  • 默认值 :60,000 毫秒(60 秒)

ngx_conf_merge_msec_value-****博客

 

conf->client_header_timeout=18446744073709551615   (无符号长整型 -1,表示未设置)
prev->client_header_timeout=18446744073709551615


执行后
conf->client_header_timeout=60000


ngx_conf_merge_size_value(conf->client_header_buffer_size, prev->client_header_buffer_size, 1024);
  • 作用 :合并 client_header_buffer_size(客户端头缓冲区大小)。
  • 默认值 :1024
     

conf->client_header_buffer_size=-1
prev->client_header_buffer_size=-1
执行后
conf->client_header_buffer_size=1024


ngx_conf_merge_bufs_value(conf->large_client_header_buffers, prev->large_client_header_buffers, 4, 8192);
  • 作用 :合并 large_client_header_buffers(大头缓冲区配置)。
  • 默认值 :4 个缓冲区,每个 8KB。

ngx_conf_merge_bufs_value-****博客

conf->large_client_header_buffers.num=0
conf->large_client_header_buffers.size=0
prev->large_client_header_buffers.num=0
prev->large_client_header_buffers.size=0
执行后
conf->large_client_header_buffers.num=4
conf->large_client_header_buffers.size=8192

 


if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
    ngx_conf_log_error(...);
    return NGX_CONF_ERROR;
}

作用 :检查 large_client_header_buffers 的大小是否 ≥ connection_pool_size

逻辑 :若不满足,记录错误并终止配置合并。

意义 :确保大头缓冲区足够容纳连接内存池,避免内存越界。

conf->large_client_header_buffers.size=8192
conf->connection_pool_size=512

条件不成立


ngx_conf_merge_value(conf->ignore_invalid_headers, prev->ignore_invalid_headers, 1);

作用 :合并 ignore_invalid_headers(是否忽略无效头)

默认值 :1(启用)

ngx_conf_merge_value-****博客

conf->ignore_invalid_headers=-1
prev->ignore_invalid_headers=-1
执行后
conf->ignore_invalid_headers=1

 


ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);

作用 :合并 merge_slashes(是否合并连续斜杠)。
默认值 :1(启用)。

conf->merge_slashes=-1
prev->merge_slashes=-1
执行后
conf->merge_slashes=1


ngx_conf_merge_value(conf->underscores_in_headers, prev->underscores_in_headers, 0);

作用 :合并 underscores_in_headers(是否允许头字段包含下划线)

默认值 :0(禁用)

conf->underscores_in_headers=-1
prev->underscores_in_headers=-1
执行后
conf->underscores_in_headers=0

 


    if (conf->server_names.nelts == 0) {
        /* the array has 4 empty preallocated elements, so push cannot fail */
        sn = ngx_array_push(&conf->server_names);
#if (NGX_PCRE)
        sn->regex = NULL;
#endif
        sn->server = conf;
        ngx_str_set(&sn->name, "");
    }

作用 :若未配置 server_name,添加默认空名称。

逻辑 :向 server_names 数组添加一个元素,名称设为空字符串。

意义 :确保每个虚拟主机至少有一个 server_name(即使为空)。

此时

conf->server_names.nelts=1

条件不成立


    sn = conf->server_names.elts;
    name = sn[0].name;
  • 作用 :获取第一个 server_name 的名称。

此时

name.data=localhost


#if (NGX_PCRE)
    if (sn->regex) {
        name.len++;
        name.data--;
    } else
#endif

作用 :如果使用正则表达式(PCRE),调整名称指针和长度。

逻辑 :正则表达式匹配的名称可能以特殊字符(如 ~)开头,需跳过。

此时

sn->regex=(nil)

条件不成立


    if (name.data[0] == '.') {
        name.len--;
        name.data++;
    }

作用 :处理通配符域名(如 .example.com)。

逻辑 :去掉开头的点,转换为 example.com,避免重复匹配。

此时

 name.data=localhost

条件不成立


    conf->server_name.len = name.len;
    conf->server_name.data = ngx_pstrdup(cf->pool, &name);
    if (conf->server_name.data == NULL) {
        return NGX_CONF_ERROR;
    }

作用 :规范化后的 server_name 存入配置。

逻辑 :使用 ngx_pstrdup 复制字符串到内存池新分配的内存

意义 :主 server_name 用于日志、错误信息等场景。

conf->server_name.len=9
conf->server_name.data=localhost


return NGX_CONF_OK;

 返回 NGX_CONF_OK