您的位置:首页 > 运维架构 > Nginx

[nginx源码分析]配置解析(server作用域)

2015-05-07 13:12 761 查看

然后进入到server

server命令在ngx_http_core_module中,如下

{ ngx_string("server"),
NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_MULTI|NGX_CONF_NOARGS,
ngx_http_core_server,
0,
0,
NULL },


ngx_http_core_server首先创建一个和ngx_http_block函数一样的上下文结构

typedef struct {
void        **main_conf;
void        **srv_conf;
void        **loc_conf;
} ngx_http_conf_ctx_t;

其中main_conf指向http上线文的main_conf

srv_conf和loc_conf都是自己创建的新的结构,包括后面进行的create_srv_conf和create_loc_conf都是和在ngx_http_block都是一致的。

同时把server信息push到http上下文中

cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];                               //这里返回的是一个srv_conf结构,
cscf->ctx = ctx;                                                                    //把这个结构中的ctx上下文,保存在这个srv_conf中的ctx中
cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
//获取ngx_http_module::main_conf[server]一个,然后把这个结构保存在server中
cscfp = ngx_array_push(&cmcf->servers);
if (cscfp == NULL) {
return NGX_CONF_ERROR;
}
*cscfp = cscf;

push到http_ctx->main_conf[0].server里面
然后保存conf,修改成server上下文
pcf = *cf;
//保存上层的http上下文,准备换成server上下文
cf->ctx = ctx;
//这里把上下文换掉了
cf->cmd_type = NGX_HTTP_SRV_CONF;

rv = ngx_conf_parse(cf, NULL);

进行回调

然后配置文件解析到listen,listen是在ngx_http_core_module中

{ ngx_string("listen"),
NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
ngx_http_core_listen,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },

ngx_http_core_listen(ngx_conf_t *cf,ngx_command_t *cmd, void *conf)

//其中cf为上面server环境中设置后的,cmd为listen cmd,conf为server_ctx->srv_conf[0]

ngx_http_core_listen回调函数主要是解析listen后面的参数,构造lsopt结构,然后调用ngx_http_add_listen,此函数首先获取main_conf

cmcf =ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

然后遍历cmcf->ports

port = cmcf->ports->elts;
for (i = 0; i < cmcf->ports->nelts; i++) {

if (p != port[i].port || sa->sa_family != port[i].family) {
continue;
}

/* a port is already in the port list */
//已经存在相同的port和family
return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
}

其中cmcf->ports是数组,遍历每一个数组,相当于key为port and family,如果有相同的地址,那么就调用ngx_http_add_addresses加入相应的port,如果没有那么就从数组里面分配一个调用ngx_http_add_addresses加入。ngx_http_add_address函数,首先遍历该port里面的server address,如果发现存在地址也相同的就加入到相同的addr->servers,如果说该port下没有相同的地址,那么就新生成一个addr,加入到addr->servers里。

整个cmcf->ports结构组织如下:

cmcf->ports /*ngx_array_t 数组中元素类型是ngx_http_conf_port_t*/
family /*ngx_int_t 网络类型*/
port	 /* int_port_t 端口*/
addrs /* ngx_array_t 数组中元素类型是ngx_http_conf_addr_t*/
ngx_http_listen_opt_t 		opt;
ngx_hash_t				hash;
ngx_hash_wildcard_t		*wc_head;
ngx_hash_wildcard_t		*wc_tail;
ngx_uint_t				nregex;
ngx_http_server_name_t	*regex;
ngx_http_core_srv_conf_t	*default_server;
ngx_array_t				servers;/*数组类型为ngx_http_core_srv_conf_t, 也就是当前server上下文*/

整个函数流程如下:



server_name命令如下:
{ ngx_string("server_name"),
NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
ngx_http_core_server_name,
NGX_HTTP_SRV_CONF_OFFSET,
0,
NULL },

从命令可以看出,上下文是server->srv_conf,因为server_name是在ngx_http_core_module模块所以索引是0,即上下文真实地址是server->srv_conf[0],然后回调函数是ngx_http_core_server_name,函数主要是加入server->srv_conf[0].server_names
struct ngx_http_server_name_s {
#if (NGX_PCRE)
ngx_http_regex_t          *regex;
#endif
ngx_http_core_srv_conf_t  *server;   /* 保存当前上下文*/
ngx_str_t                  name; /*server name*/
};

下面先讲error_page,因为location比较长
{ ngx_string("error_page"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_2MORE,
ngx_http_core_error_page,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },

这样error_page信息,保存在server->loc_conf,因为命令是在ngx_http_core_module里,所以准确的存放位置是server->loc_conf[0],具体代码:
for (i = 1; i < cf->args->nelts - n; i++) {
err = ngx_array_push(clcf->error_pages);//增加一个err
if (err == NULL) {
return NGX_CONF_ERROR;
}

err->status = ngx_atoi(value[i].data, value[i].len);//设置状态吗

if (err->status == NGX_ERROR || err->status == 499) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid value \"%V\"", &value[i]);
return NGX_CONF_ERROR;
}

if (err->status < 300 || err->status > 599) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"value \"%V\" must be between 300 and 599",
&value[i]);
return NGX_CONF_ERROR;
}

err->overwrite = overwrite;
if (overwrite == -1) {
switch (err->status) {
case NGX_HTTP_TO_HTTPS:
case NGX_HTTPS_CERT_ERROR:
case NGX_HTTPS_NO_CERT:
err->overwrite = NGX_HTTP_BAD_REQUEST;
default:
break;
}
}
err->value = cv;
err->args = args;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nginx