ngx_http_core_server

复制代码
static char *
ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
    char                        *rv;
    void                        *mconf;
    size_t                       len;
    u_char                      *p;
    ngx_uint_t                   i;
    ngx_conf_t                   pcf;
    ngx_http_module_t           *module;
    struct sockaddr_in          *sin;
    ngx_http_conf_ctx_t         *ctx, *http_ctx;
    ngx_http_listen_opt_t        lsopt;
    ngx_http_core_srv_conf_t    *cscf, **cscfp;
    ngx_http_core_main_conf_t   *cmcf;

    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
    if (ctx == NULL) {
        return NGX_CONF_ERROR;
    }

    http_ctx = cf->ctx;
    ctx->main_conf = http_ctx->main_conf;

    /* the server{}'s srv_conf */

    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->srv_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    /* the server{}'s loc_conf */

    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->loc_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    for (i = 0; cf->cycle->modules[i]; i++) {
        if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[i]->ctx;

        if (module->create_srv_conf) {
            mconf = module->create_srv_conf(cf);
            if (mconf == NULL) {
                return NGX_CONF_ERROR;
            }

            ctx->srv_conf[cf->cycle->modules[i]->ctx_index] = mconf;
        }

        if (module->create_loc_conf) {
            mconf = module->create_loc_conf(cf);
            if (mconf == NULL) {
                return NGX_CONF_ERROR;
            }

            ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf;
        }
    }


    /* the server configuration context */

    cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
    cscf->ctx = ctx;


    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];

    cscfp = ngx_array_push(&cmcf->servers);
    if (cscfp == NULL) {
        return NGX_CONF_ERROR;
    }

    *cscfp = cscf;


    /* parse inside server{} */

    pcf = *cf;
    cf->ctx = ctx;
    cf->cmd_type = NGX_HTTP_SRV_CONF;

    rv = ngx_conf_parse(cf, NULL);

    *cf = pcf;

    if (rv == NGX_CONF_OK && !cscf->listen) {
        ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));

        p = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
        if (p == NULL) {
            return NGX_CONF_ERROR;
        }

        lsopt.sockaddr = (struct sockaddr *) p;

        sin = (struct sockaddr_in *) p;

        sin->sin_family = AF_INET;
#if (NGX_WIN32)
        sin->sin_port = htons(80);
#else
        sin->sin_port = htons((getuid() == 0) ? 80 : 8000);
#endif
        sin->sin_addr.s_addr = INADDR_ANY;

        lsopt.socklen = sizeof(struct sockaddr_in);

        lsopt.backlog = NGX_LISTEN_BACKLOG;
        lsopt.rcvbuf = -1;
        lsopt.sndbuf = -1;
#if (NGX_HAVE_SETFIB)
        lsopt.setfib = -1;
#endif
#if (NGX_HAVE_TCP_FASTOPEN)
        lsopt.fastopen = -1;
#endif
        lsopt.wildcard = 1;

        len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;

        p = ngx_pnalloc(cf->pool, len);
        if (p == NULL) {
            return NGX_CONF_ERROR;
        }

        lsopt.addr_text.data = p;
        lsopt.addr_text.len = ngx_sock_ntop(lsopt.sockaddr, lsopt.socklen, p,
                                            len, 1);

        if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) {
            return NGX_CONF_ERROR;
        }
    }

    return rv;
}

ngx_http_core_server 函数是 Nginx 在解析配置文件中 server{} 块时的核心处理函数


复制代码
    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
    if (ctx == NULL) {
        return NGX_CONF_ERROR;
    }

server{} 块的配置上下文分配内存

ngx_http_conf_ctx_t 是 Nginx HTTP 配置的核心结构体,用于存储 server{} 块的配置上下文(包括 main_confsrv_confloc_conf 三个配置数组)

复制代码
    http_ctx = cf->ctx;
    ctx->main_conf = http_ctx->main_conf;

在解析 server{} 块时,cf->ctx 指向的是全局的 HTTP 配置上下文(即 main 级别的配置上下文)。

通过赋值给 http_ctx,将全局上下文保存到临时变量中,避免后续因 cf->ctx 被修改而丢失对全局配置的引用。

http_ctx->main_conf 是全局 HTTP 配置中的 main_conf 数组,存储所有 HTTP 模块的 main 级配置。

ctx->main_conf 是当前 server{} 块上下文中的 main_conf 指针。

通过直接赋值,使 server{} 块的 main_conf 指向全局的 main_conf,实现配置继承

复制代码
    /* the server{}'s srv_conf */

    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->srv_conf == NULL) {
        return NGX_CONF_ERROR;
    }

server{} 块的 srv_conf 数组分配内存

复制代码
   /* the server{}'s loc_conf */

    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->loc_conf == NULL) {
        return NGX_CONF_ERROR;
    }

server{} 块的 loc_conf 数组分配内存

复制代码
    for (i = 0; cf->cycle->modules[i]; i++) {
        if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
            continue;
        }

遍历,跳过非NGX_HTTP_MODULE模块

复制代码
module = cf->cycle->modules[i]->ctx;

获取模块的上下文

复制代码
if (module->create_srv_conf) {
            mconf = module->create_srv_conf(cf);
            if (mconf == NULL) {
                return NGX_CONF_ERROR;
            }

            ctx->srv_conf[cf->cycle->modules[i]->ctx_index] = mconf;
        }

create_srv_conf 是模块定义的函数指针,用于创建该模块的 server 级配置结构体

复制代码
if (module->create_loc_conf) {
            mconf = module->create_loc_conf(cf);
            if (mconf == NULL) {
                return NGX_CONF_ERROR;
            }

            ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf;
        }

用于创建该模块的 location 级配置结构体

复制代码
    /* the server configuration context */

    cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
    cscf->ctx = ctx;

获取核心模块(ngx_http_core_module)的 server 级配置结构体

server{} 块的配置上下文(ctx)关联到核心模块的配置结构体

复制代码
cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];

访问当前 server{} 块上下文中的 main_conf 数组

获取核心模块(ngx_http_core_module)的 main 级配置

ctx 是当前 server{} 块的配置上下文

main_conf ,指向全局的 main 级配置数组。

该数组存储了所有 HTTP 模块的 main 级配置结构体指针

配置继承 :server{} 块通过 main_conf 继承全局配置

全局数据访问 :main_conf 是全局唯一的,所有 server{} 块共享同一份 main_conf

复制代码
    cscfp = ngx_array_push(&cmcf->servers);
    if (cscfp == NULL) {
        return NGX_CONF_ERROR;
    }

将当前 server{} 块的核心配置指针添加到全局服务器列表

cmcf->servers 是核心模块全局配置(ngx_http_core_main_conf_t)中的动态数组,存储所有 server{} 块的 ngx_http_core_srv_conf_t 指针。

复制代码
*cscfp = cscf;

*cscfp = cscf 是将cscf的值(即当前server的核心配置结构体指针)存储到动态数组中的新位置

将当前 server{} 块的核心配置指针赋值给动态数组中的新元素

复制代码
    /* parse inside server{} */

    pcf = *cf;
    cf->ctx = ctx;
    cf->cmd_type = NGX_HTTP_SRV_CONF;

    rv = ngx_conf_parse(cf, NULL);

    *cf = pcf;

保存当前配置解析上下文的状态

将配置解析上下文切换为当前 server{} 块的上下文

设置当前解析的指令类型为 server 级指令

递归解析 server{} 块内部的配置指令

恢复原始的配置解析上下文


进入 ngx_conf_parse

复制代码
else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {

        type = parse_block;

进入这个条件

然后

复制代码
   for ( ;; ) {
        rc = ngx_conf_read_token(cf);

循环,读取 token

接下来读到的是

listen 80

;作为结束

然后

复制代码
rc = ngx_conf_handler(cf, rc);

处理当前读取的 token


进入 ngx_conf_handler

复制代码
static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    char           *rv;
    void           *conf, **confp;
    ngx_uint_t      i, found;
    ngx_str_t      *name;
    ngx_command_t  *cmd;

    name = cf->args->elts;

    found = 0;

当前要处理的指令是 listen

name->data=listen

复制代码
    for (i = 0; cf->cycle->modules[i]; i++) {

        cmd = cf->cycle->modules[i]->commands;
        if (cmd == NULL) {
            continue;
        }

        for ( /* void */ ; cmd->name.len; cmd++) {

            if (name->len != cmd->name.len) {
                continue;
            }

            if (ngx_strcmp(name->data, cmd->name.data) != 0) {
                continue;
            }

循环,查找 listen 指令

直到

i=9

modules[9]->name=ngx_http_core_module

然后通过语法检查

接下来

复制代码
            else if (cf->ctx) {
                confp = *(void **) ((char *) cf->ctx + cmd->conf);

                if (confp) {
                    conf = confp[cf->cycle->modules[i]->ctx_index];
                }
            }

此时

**cmd->conf=8

ctx_index=0**

cmd->conf 是一个关键字段,用于定位指令对应的配置存储位置

cmd->confngx_command_t 结构体中的一个字段,表示 配置存储的偏移量 。它决定了该指令的配置值应被存储到哪个配置块(如 mainserverlocation 等)的内存区域中。

此时 cf->ctx 指向一个 ngx_http_conf_ctx_t 结构体

ngx_http_conf_ctx_t -CSDN博客

(char *) cf->ctx + cmd->conf

也就是跳过了 结构体中的第一个字段,指向结构体的第二个字段 srv_conf

srv_conf 用来 存储 server 级别的配置数据 (当前正处于 server 块中)

接下来

复制代码
rv = cmd->set(cf, cmd, conf);

此时的 cmd->set 是 ngx_http_core_module 的 listen指令的set

是 ngx_http_core_listen

ngx_http_core_listen-CSDN博客


复制代码
            if (rv == NGX_CONF_OK) {
                return NGX_OK;
            }

返回 NGX_OK


回到 ngx_conf_parse

复制代码
rc = ngx_conf_read_token(cf);

继续 读取配置文件 接下来的 token

接下来要读取的 token 是 37行的

server_name localhost 以 ;为结束

server_name localhost; 是 Nginx 配置中的关键指令,用于定义虚拟主机(Virtual Host)的域名或标识符。它的核心作用是 根据 HTTP 请求的 Host 头字段匹配对应的服务器配置块 ,从而确保 Nginx 能正确路由请求到目标服务

复制代码
rc = ngx_conf_handler(cf, rc);

处理读取的 token


进入 ngx_conf_handler

复制代码
static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    char           *rv;
    void           *conf, **confp;
    ngx_uint_t      i, found;
    ngx_str_t      *name;
    ngx_command_t  *cmd;

    name = cf->args->elts;

    found = 0;

此时 name->data=server_name

此时要处理的指令是 server_name

复制代码
    for (i = 0; cf->cycle->modules[i]; i++) {

        cmd = cf->cycle->modules[i]->commands;
        if (cmd == NULL) {
            continue;
        }

        for ( /* void */ ; cmd->name.len; cmd++) {

            if (name->len != cmd->name.len) {
                continue;
            }

            if (ngx_strcmp(name->data, cmd->name.data) != 0) {
                continue;
            }

            found = 1;

遍历查找 server_name 指令

直到 i=9

modules[9]->name=ngx_http_core_module

在 ngx_http_core_module 模块中找到了 server_name 指令

cmd->name.data=server_name

然后通过语法检查之后

复制代码
         else if (cf->ctx) {
                confp = *(void **) ((char *) cf->ctx + cmd->conf);

                if (confp) {
                    conf = confp[cf->cycle->modules[i]->ctx_index];
                }
            }

**cmd->conf=8

ctx_index=0**

复制代码
            rv = cmd->set(cf, cmd, conf);

此时的 cmd->set 是 ngx_http_core_module 模块的 server_name 指令 的set 函数指针

ngx_http_core_server_name

ngx_http_core_server_name-CSDN博客

复制代码
            if (rv == NGX_CONF_OK) {
                return NGX_OK;
            }

返回 NGX_OK


回到 ngx_conf_parse

复制代码
rc = ngx_conf_read_token(cf);

继续读取 token

跳过注释和空行 接下来是 43 行的

location / {

以{ 为结束

复制代码
rc = ngx_conf_handler(cf, rc);

处理 token


进入 ngx_conf_handler

复制代码
static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    char           *rv;
    void           *conf, **confp;
    ngx_uint_t      i, found;
    ngx_str_t      *name;
    ngx_command_t  *cmd;

    name = cf->args->elts;

    found = 0;

此时 name->data=location

复制代码
    for (i = 0; cf->cycle->modules[i]; i++) {

        cmd = cf->cycle->modules[i]->commands;
        if (cmd == NULL) {
            continue;
        }

        for ( /* void */ ; cmd->name.len; cmd++) {

            if (name->len != cmd->name.len) {
                continue;
            }

            if (ngx_strcmp(name->data, cmd->name.data) != 0) {
                continue;
            }

            found = 1;

遍历查找 location 指令

直到

i=9

modules[9]->name=ngx_http_core_module

复制代码
            else if (cf->ctx) {
                confp = *(void **) ((char *) cf->ctx + cmd->conf);

                if (confp) {
                    conf = confp[cf->cycle->modules[i]->ctx_index];
                }
            }

cmd->conf=8
ctx_index=0

复制代码
rv = cmd->set(cf, cmd, conf);

此时 是ngx_http_core_module 模块的 location 指令 的set 函数指针

是 ngx_http_core_location

ngx_http_core_location-CSDN博客

复制代码
            if (rv == NGX_CONF_OK) {
                return NGX_OK;
            }

返回 NGX_OK


回到 ngx_conf_parse

复制代码
rc = ngx_conf_read_token(cf);

继续读取 token

接下来读取的是

error_page 500 502 503 504 /50x.html

以 ;为结束
这行配置的作用是:当 Nginx 服务器遇到指定的 HTTP 错误状态码(500、502、503、504)时,自动将客户端请求重定向到自定义的错误页面 /50x.html ,而不是显示默认的 Nginx 错误页面

error_page
这是 Nginx 的指令,用于定义当服务器发生错误时返回的自定义页面。

500 502 503 504
这些是 HTTP 状态码,分别表示:

500 :内部服务器错误(Internal Server Error)。

502 :网关错误(Bad Gateway),通常由上游服务器(如 PHP、反向代理)响应无效内容导致。

503 :服务不可用(Service Unavailable),通常因服务器过载或维护触发。

504 :网关超时(Gateway Timeout),上游服务器未及时响应。

/50x.html
这是自定义错误页面的路径(相对于 Nginx 的根目录 root)。

复制代码
rc = ngx_conf_handler(cf, rc);

处理读取的 token

复制代码
static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    char           *rv;
    void           *conf, **confp;
    ngx_uint_t      i, found;
    ngx_str_t      *name;
    ngx_command_t  *cmd;

    name = cf->args->elts;

    found = 0;

此时 name->data=error_page

当前要处理的指令是 error_page

复制代码
   for (i = 0; cf->cycle->modules[i]; i++) {

        cmd = cf->cycle->modules[i]->commands;
        if (cmd == NULL) {
            continue;
        }

        for ( /* void */ ; cmd->name.len; cmd++) {

            if (name->len != cmd->name.len) {
                continue;
            }

            if (ngx_strcmp(name->data, cmd->name.data) != 0) {
                continue;
            }

            found = 1;

循环查找 error_page 指令

直到

i=9

modules[9]->name=ngx_http_core_module

复制代码
            else if (cf->ctx) {
                confp = *(void **) ((char *) cf->ctx + cmd->conf);

                if (confp) {
                    conf = confp[cf->cycle->modules[i]->ctx_index];
                }
            }

获取对应的配置结构的指针

此时

cmd->conf=16
ctx_index=0

复制代码
rv = cmd->set(cf, cmd, conf);

处理 token

此时 是 ngx_http_core_module 模块的 error_page 指令的 set

指向的是 ngx_http_core_error_page

ngx_http_core_error_page-CSDN博客

复制代码
            if (rv == NGX_CONF_OK) {
                return NGX_OK;
            }

返回 NGX_OK


相关推荐
tingting011940 分钟前
k8s 1.30 安装ingress-nginx
nginx·容器·kubernetes
残花月伴1 小时前
linux详细安装/配置(mysql/nginx/tomcat)
linux·mysql·nginx
Cloud_.5 小时前
用Nginx实现负载均衡与高可用架构(整合Keepalived)
nginx·架构·负载均衡·keepalived
Shi_haoliu6 小时前
各种网址整理-vue,前端,linux,ai前端开发,各种开发能用到的网址和一些有用的博客
linux·前端·javascript·vue.js·nginx·前端框架·pdf
LYX369311 小时前
nginx https配置
运维·nginx
java搬砖工-苤-初心不变12 小时前
关于 Nginx 配置中 proxy_set_header Host $host 的作用及其对 HTTP 请求头影响的详细说明,结合示例展示设置前后的差异
网络·nginx·http
裁二尺秋风14 小时前
Nginx — Nginx处理Web请求机制解析
前端·nginx
Kendra9191 天前
Keepalive+LVS+Nginx+NFS高可用架构
nginx·架构·lvs
若云止水1 天前
ngx_http_core_main_conf_t
nginx
开发小能手-roy1 天前
Ubuntu 系统中安装 Nginx
数据库·nginx·ubuntu