定义在 src\http\ngx_http_core_module.c
static char *
ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ngx_http_core_loc_conf_t *clcf = conf;ngx_str_t                  *value;ngx_int_t                   alias;ngx_uint_t                  n;ngx_http_script_compile_t   sc;alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;if (clcf->root.data) {if ((clcf->alias != 0) == alias) {return "is duplicate";}ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"\"%V\" directive is duplicate, ""\"%s\" directive was specified earlier",&cmd->name, clcf->alias ? "alias" : "root");return NGX_CONF_ERROR;}if (clcf->named && alias) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"the \"alias\" directive cannot be used ""inside the named location");return NGX_CONF_ERROR;}value = cf->args->elts;if (ngx_strstr(value[1].data, "$document_root")|| ngx_strstr(value[1].data, "${document_root}")){ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"the $document_root variable cannot be used ""in the \"%V\" directive",&cmd->name);return NGX_CONF_ERROR;}if (ngx_strstr(value[1].data, "$realpath_root")|| ngx_strstr(value[1].data, "${realpath_root}")){ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"the $realpath_root variable cannot be used ""in the \"%V\" directive",&cmd->name);return NGX_CONF_ERROR;}clcf->alias = alias ? clcf->name.len : 0;clcf->root = value[1];if (!alias && clcf->root.len > 0&& clcf->root.data[clcf->root.len - 1] == '/'){clcf->root.len--;}if (clcf->root.data[0] != '$') {if (ngx_conf_full_name(cf->cycle, &clcf->root, 0) != NGX_OK) {return NGX_CONF_ERROR;}}n = ngx_http_script_variables_count(&clcf->root);ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));sc.variables = n;#if (NGX_PCRE)if (alias && clcf->regex) {clcf->alias = NGX_MAX_SIZE_T_VALUE;n = 1;}
#endifif (n) {sc.cf = cf;sc.source = &clcf->root;sc.lengths = &clcf->root_lengths;sc.values = &clcf->root_values;sc.complete_lengths = 1;sc.complete_values = 1;if (ngx_http_script_compile(&sc) != NGX_OK) {return NGX_CONF_ERROR;}}return NGX_CONF_OK;
}
ngx_http_core_root函数是 Nginx 中处理root和alias配置指令的核心逻辑实现
alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;通过指令名称长度判断当前处理的是
root还是alias指令当前的指令是 root
所以 alias=0
    if (clcf->root.data) {if ((clcf->alias != 0) == alias) {return "is duplicate";}ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"\"%V\" directive is duplicate, ""\"%s\" directive was specified earlier",&cmd->name, clcf->alias ? "alias" : "root");return NGX_CONF_ERROR;}逻辑 :
clcf->root.data是存储路径值的指针。若非空,说明当前配置块(如location)已设置过root或alias。意义 :避免重复或冲突的路径配置。
同一指令重复 (如两次
root):直接返回"is duplicate"不同指令冲突 (如
root后跟alias):记录详细日志后终止
    if (clcf->named && alias) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"the \"alias\" directive cannot be used ""inside the named location");return NGX_CONF_ERROR;}
clcf->named:表示当前location是一个命名 location(如location @name)。
alias:当前指令是alias(值为1)。若两者同时为真,触发错误逻辑。
意义 :命名 location 的特殊用途与
alias的路径替换逻辑存在冲突此时 clcf->named=0 alias=0
条件不成立
    value = cf->args->elts;if (ngx_strstr(value[1].data, "$document_root")|| ngx_strstr(value[1].data, "${document_root}")){ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"the $document_root variable cannot be used ""in the \"%V\" directive",&cmd->name);return NGX_CONF_ERROR;}禁止在
root或alias指令中直接使用$document_root或${document_root}变量
- 逻辑 :通过
ngx_strstr函数检查路径参数(value[1])中是否包含变量$document_root或${document_root}。- 意义 :直接使用这些变量会导致循环依赖 ,因为
$document_root的值正是由root/alias指令定义的。此时
value[1].data=html
条件不成立
    if (ngx_strstr(value[1].data, "$realpath_root")|| ngx_strstr(value[1].data, "${realpath_root}")){ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"the $realpath_root variable cannot be used ""in the \"%V\" directive",&cmd->name);return NGX_CONF_ERROR;}禁止在
root或alias指令中直接使用$realpath_root或${realpath_root}变量此时条件不成立
    clcf->alias = alias ? clcf->name.len : 0;clcf->root = value[1];
clcf->alias = alias ? clcf->name.len : 0;
作用 :
设置clcf->alias的值,用于标识当前配置是alias还是root,并记录alias的替换长度。
逻辑 :
alias是一个布尔变量:
1表示当前处理的是alias指令。
0表示当前处理的是root指令。
若为
alias:
clcf->alias被赋值为clcf->name.len(即当前location名称的长度)。若为
root:
clcf->alias被置为0
clcf->root = value[1];
作用 :
将用户配置的路径值保存到clcf->root中。
逻辑 :
value[1]是指令的参数列表中的第二个元素(索引从0开始)此时
clcf->alias=0
clcf->root=html
    if (!alias && clcf->root.len > 0&& clcf->root.data[clcf->root.len - 1] == '/'){clcf->root.len--;}
!alias:仅对root指令生效(alias为0时为root)。
clcf->root.len > 0:确保路径非空,避免无效操作。
clcf->root.data[clcf->root.len - 1] == '/':检查路径末尾是否为斜杠/若当前是
root指令,且路径非空且以/结尾,则进入处理逻辑将路径的长度减
1,隐式删除末尾的斜杠避免拼接 URI 时可能出现双斜杠
此时条件不成立
    if (clcf->root.data[0] != '$') {if (ngx_conf_full_name(cf->cycle, &clcf->root, 0) != NGX_OK) {return NGX_CONF_ERROR;}}
clcf->root.data[0]是路径的第一个字符。若不以
$开头,表示路径是静态字符串 ,而非变量(如$document_root)。意义 :
仅对静态路径进行规范化处理,变量路径需在运行时动态解析。
ngx_conf_full_name将相对路径转换为绝对路径 。参数
cf->cycle:Nginx 全局配置上下文。参数
&clcf->root:待处理的路径。参数
0:标志位(此处未启用特殊选项,如符号链接解析)。示例 :
若 Nginx 前缀为/usr/local/nginx,用户配置root html;,则转换后路径为/usr/local/nginx/html。此时 root.data=/usr/local/nginx/html
n = ngx_http_script_variables_count(&clcf->root);
ngx_http_script_variables_count遍历路径字符串(clcf->root),统计符合变量格式($var或${var})的出现次数。示例 :
路径"/var/www/$host/$uri"包含 2 个变量 ($host和$uri),因此n = 2。设计目的
动态路径预处理 :
若n > 0,表示路径需要运行时动态解析变量,后续需通过脚本引擎(ngx_http_script)生成解析逻辑。
若n = 0,路径为静态字符串,直接使用即可。ngx_http_script_variables_count-CSDN博客
此时 n = 0
    ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));sc.variables = n;
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
作用 :
初始化ngx_http_script_compile_t结构体变量sc,将其所有字段置零 。
sc.variables = n;
作用 :
设置脚本编译器的变量数量 ,即路径中需要动态解析的变量个数。ngx_http_script_compile_t-CSDN博客
#if (NGX_PCRE)if (alias && clcf->regex) {clcf->alias = NGX_MAX_SIZE_T_VALUE;n = 1;}
#endifif (alias && clcf->regex)
当前处理的是 alias
当前使用了正则表达式匹配
此时
alias=0
clcf->regex=NULL条件不成立
    if (n) {sc.cf = cf;sc.source = &clcf->root;sc.lengths = &clcf->root_lengths;sc.values = &clcf->root_values;sc.complete_lengths = 1;sc.complete_values = 1;if (ngx_http_script_compile(&sc) != NGX_OK) {return NGX_CONF_ERROR;}}
if (n) {
- 作用 :
检查路径中是否包含变量(n > 0)。若存在变量,进入动态路径编译流程条件不成立
    return NGX_CONF_OK;返回 NGX_CONF_OK;
