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

然後進入到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;
     }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章