结构体定义:
// 指令结构体,用于定义nginx指令
// ngx_command_t (ngx_core.h)
struct ngx_command_s {
//指令的名字
ngx_str_t name;
//指令的类型,是NGX_CONF_XXX的组合,决定指令出现的位置、参数数量、类型等
// NGX_HTTP_MAIN_CONF/NGX_HTTP_SRV_CONF/NGX_HTTP_LOC_CONF
ngx_uint_t type;
// 指令解析函数,是函数指针
// 预设有ngx_conf_set_flag_slot等,见本文件
// cf:解析的环境结构体,重要的是cf->args,是指令字符串数组
// cmd:该指令的结构体
// conf当前的配置结构体,需转型后才能使用
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
// 专门给http/stream模块使用,决定存储在main/srv/loc的哪个层次
// NGX_HTTP_MAIN_CONF_OFFSET/NGX_HTTP_SRV_CONF_OFFSET/NGX_HTTP_LOC_CONF_OFFSET
// NGX_STREAM_MAIN_CONF_OFFSET
// 其他类型的模块不使用,直接为0
ngx_uint_t conf;
// 变量在conf结构体里的偏移量,可用offsetof得到
// 主要用于nginx内置的命令解析函数,自己写命令解析函数可以置为0
ngx_uint_t offset;
//解析后处理的数据
void *post;
};
多态函数调用搜索关键字-ngx_conf_file.c:
rv = cmd->set(cf, cmd, conf);
看看这个:
static char *
ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf = conf;
char *rv;
ngx_conf_t save;
if (clcf->types == NULL) {
clcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
if (clcf->types == NULL) {
return NGX_CONF_ERROR;
}
}
save = *cf;
cf->handler = ngx_http_core_type;
cf->handler_conf = conf;
rv = ngx_conf_parse(cf, NULL);
*cf = save;
return rv;
}
char *
ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *p = conf;
ngx_str_t *field, *value;
ngx_conf_post_t *post;
field = (ngx_str_t *) (p + cmd->offset);
if (field->data) {
return "is duplicate";
}
value = cf->args->elts;
*field = value[1];
if (cmd->post) {
post = cmd->post;
return post->post_handler(cf, post, field);
}
return NGX_CONF_OK;
}
比较这两个set函数,ngx_http_core_types这个函数里将cf->handler赋值了,但是
ngx_conf_set_str_slot没有,所以在ngx_conf_parse中:
char *
ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
{
for ( ;; ) {
rc = ngx_conf_read_token(cf);
// ...
if (cf->handler)
{
/*
* the custom handler, i.e., that is used in the http's
* "types { ... }" directive
*/
if (rc == NGX_CONF_BLOCK_START) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\"");
goto failed;
}
// 特殊的解析处理函数,可以自己定义{}的解析处理,比较自由
// 例如 types {}、content_by_lua_block {}
//printf("file = %s, line= %d, func =%s.\n",__FILE__,__LINE__,__func__);
rv = (*cf->handler)(cf, NULL, cf->handler_conf);
//printf("file = %s, line= %d, func =%s.\n",__FILE__,__LINE__,__func__);
if (rv == NGX_CONF_OK) {
//printf("file = %s, line= %d, func =%s.\n",__FILE__,__LINE__,__func__);
continue;
}
if (rv == NGX_CONF_ERROR) {
goto failed;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", rv);
goto failed;
}
}
}
再看一个例子,它的handler也会被赋值:
char *
ngx_http_lua_content_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
char *rv;
ngx_conf_t save;
save = *cf;
cf->handler = ngx_http_lua_content_by_lua;
cf->handler_conf = conf;
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
*cf = save;
return rv;
}
cmdname = access_log. cmdtype = ce000800. cmdsetfunc = ngx_http_log_set_log
cmdname = add_header. cmdtype = 4e00000c. cmdsetfunc = ngx_http_headers_expires
cmdname = body_filter_by_lua_file. cmdtype = 4e000002. cmdsetfunc = ngx_http_lua_body_filter_by_lua
cmdname = client_body_buffer_size. cmdtype = e000002. cmdsetfunc = ngx_conf_set_size_slot
cmdname = client_body_temp_path. cmdtype = e00001e. cmdsetfunc = ngx_conf_set_path_slot
cmdname = client_max_body_size. cmdtype = e000002. cmdsetfunc = ngx_conf_set_off_slot
cmdname = default_type. cmdtype = e000002. cmdsetfunc = ngx_conf_set_str_slot
cmdname = error_log. cmdtype = e000800. cmdsetfunc = ngx_error_log|ngx_http_core_error_log|ngx_mail_core_error_log|ngx_stream_core_error_log
cmdname = error_page. cmdtype = 4e001000. cmdsetfunc = ngx_http_core_error_page
cmdname = events. cmdtype = 1000101. cmdsetfunc = ngx_events_block
cmdname = gzip. cmdtype = 4e000200. cmdsetfunc = ngx_conf_set_flag_slot
cmdname = gzip_comp_level. cmdtype = e000002. cmdsetfunc = ngx_conf_set_num_slot
cmdname = gzip_disable. cmdtype = e000800. cmdsetfunc = ngx_http_gzip_disable
cmdname = gzip_min_length. cmdtype = e000002. cmdsetfunc = ngx_conf_set_size_slot
cmdname = gzip_types. cmdtype = e000800. cmdsetfunc = ngx_conf_set_size_slot
cmdname = gzip_vary. cmdtype = e000200. cmdsetfunc = ngx_conf_set_flag_slot
cmdname = http. cmdtype = 1000101. cmdsetfunc = ngx_http_block
cmdname = if. cmdtype = c000900. cmdsetfunc = ngx_http_rewrite_if|
cmdname = include. cmdtype = ff000002. cmdsetfunc = ngx_conf_include
cmdname = init_by_lua_file. cmdtype = 2000002. cmdsetfunc = ngx_http_lua_init_by_lua
cmdname = keepalive_timeout. cmdtype = e000006. cmdsetfunc = ngx_http_core_keepalive|ngx_conf_set_msec_slot
cmdname = large_client_header_buffers. cmdtype = 6000004. cmdsetfunc = ngx_conf_set_bufs_slot
cmdname = listen. cmdtype = 4000800. cmdsetfunc = ngx_http_core_listen|ngx_mail_core_listen|ngx_stream_core_listen
cmdname = location. cmdtype = c000106. cmdsetfunc = ngx_http_core_location
cmdname = log_format. cmdtype = 2001000. cmdsetfunc = ngx_http_log_set_format|ngx_stream_log_set_format
cmdname = lua_code_cache. cmdtype = 4e000200. cmdsetfunc = ngx_http_lua_code_cache
cmdname = lua_shared_dict. cmdtype = 2000004. cmdsetfunc = ngx_http_lua_shared_dict
cmdname = map. cmdtype = 2000104. cmdsetfunc = ngx_http_map_block|ngx_stream_map_block
cmdname = multi_accept. cmdtype = 2000200. cmdsetfunc = ngx_conf_set_flag_slot
cmdname = proxy_buffering. cmdtype = e000200. cmdsetfunc = ngx_conf_set_flag_slot
cmdname = proxy_buffers. cmdtype = e000004. cmdsetfunc = ngx_conf_set_bufs_slot
cmdname = proxy_buffer_size. cmdtype = e000002. cmdsetfunc = ngx_conf_set_size_slot|ngx_conf_set_size_slot
cmdname = proxy_busy_buffers_size. cmdtype = e000002. cmdsetfunc = ngx_conf_set_size_slot
cmdname = proxy_cache_path. cmdtype = 2001000. cmdsetfunc = ngx_http_file_cache_set_slot
cmdname = proxy_connect_timeout. cmdtype = e000002. cmdsetfunc = ngx_conf_set_msec_slot|ngx_conf_set_msec_slot
cmdname = proxy_http_version. cmdtype = e000002. cmdsetfunc = ngx_conf_set_enum_slot
cmdname = proxy_pass. cmdtype = c8000002. cmdsetfunc = ngx_http_proxy_pass|ngx_stream_proxy_pass
cmdname = proxy_read_timeout. cmdtype = e000002. cmdsetfunc = ngx_conf_set_msec_slot
cmdname = proxy_send_timeout. cmdtype = e000002. cmdsetfunc = ngx_conf_set_msec_slot
cmdname = proxy_set_header. cmdtype = e000004. cmdsetfunc = ngx_conf_set_keyval_slot
cmdname = proxy_temp_file_write_size. cmdtype = e000002. cmdsetfunc = ngx_conf_set_size_slot
cmdname = return. cmdtype = 6c000006. cmdsetfunc = ngx_http_rewrite_return|ngx_stream_return
cmdname = rewrite_by_lua_file. cmdtype = 4e000002. cmdsetfunc = ngx_http_lua_rewrite_by_lua
cmdname = root. cmdtype = 4e000002. cmdsetfunc = ngx_http_core_root
cmdname = sendfile. cmdtype = 4e000200. cmdsetfunc = ngx_conf_set_flag_slot
cmdname = server. cmdtype = 10000800. cmdsetfunc = ngx_http_core_server|ngx_http_upstream_server|ngx_mail_core_server|ngx_stream_core_server|ngx_stream_upstream_server
cmdname = server. cmdtype = 2000101. cmdsetfunc = ngx_http_core_server|ngx_http_upstream_server|ngx_mail_core_server|ngx_stream_core_server|ngx_stream_upstream_server
cmdname = server_name. cmdtype = 4000800. cmdsetfunc = ngx_http_core_server_name|ngx_conf_set_str_slot
cmdname = set. cmdtype = 6c000004. cmdsetfunc = ngx_http_rewrite_set|ngx_stream_set
cmdname = ssl_certificate. cmdtype = 6000002. cmdsetfunc = ngx_conf_set_str_array_slot|ngx_conf_set_str_array_slot|ngx_conf_set_str_array_slot
cmdname = ssl_certificate_key. cmdtype = 6000002. cmdsetfunc = ngx_conf_set_str_array_slot|ngx_conf_set_str_array_slot|ngx_conf_set_str_array_slot
cmdname = ssl_ciphers. cmdtype = 6000002. cmdsetfunc = ngx_conf_set_str_slot|ngx_conf_set_str_slot|ngx_conf_set_str_slot
cmdname = ssl_prefer_server_ciphers. cmdtype = 6000200. cmdsetfunc = ngx_conf_set_flag_slot|ngx_conf_set_flag_slot|ngx_conf_set_flag_slot
cmdname = ssl_session_cache. cmdtype = 6000006. cmdsetfunc = ngx_http_ssl_session_cache|ngx_mail_ssl_session_cache|ngx_stream_ssl_session_cache
cmdname = ssl_session_timeout. cmdtype = 6000002. cmdsetfunc = ngx_conf_set_sec_slot|ngx_conf_set_sec_slot|ngx_conf_set_sec_slot
cmdname = sub_filter_once. cmdtype = e000200. cmdsetfunc = ngx_conf_set_flag_slot
cmdname = subs_filter. cmdtype = e001000. cmdsetfunc = ngx_http_subs_filter
cmdname = subs_filter_types. cmdtype = e000800. cmdsetfunc = ngx_http_types_slot
cmdname = types. cmdtype = e000101. cmdsetfunc = ngx_http_core_types
cmdname = upstream. cmdtype = 2000102. cmdsetfunc = ngx_http_upstream|ngx_stream_upstream
cmdname = use. cmdtype = 2000002. cmdsetfunc = ngx_event_use
cmdname = user. cmdtype = 1010006. cmdsetfunc = ngx_set_user
cmdname = user_login. cmdtype = 8000001. cmdsetfunc = ngx_http_user_login
cmdname = worker_connections. cmdtype = 2000002. cmdsetfunc = ngx_event_connections
cmdname = worker_processes. cmdtype = 1010002. cmdsetfunc = ngx_set_worker_processes
cmdname = worker_rlimit_nofile. cmdtype = 1010002. cmdsetfunc = ngx_conf_set_num_slot