当前位置: 首页 > article >正文

ngx_http_core_root

定义在 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;
    }
#endif

    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;
        }
    }

    return NGX_CONF_OK;
}

ngx_http_core_root 函数是 Nginx 中处理 rootalias 配置指令的核心逻辑实现


 

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)已设置过 rootalias

意义 :避免重复或冲突的路径配置。

同一指令重复 (如两次 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;
    }

 禁止在 rootalias 指令中直接使用 $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;
    }

禁止在 rootalias 指令中直接使用 $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 指令生效(alias0 时为 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;
        }
    #endif

     if (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;



    http://www.kler.cn/a/610256.html

    相关文章:

  • ngx_http_core_error_page
  • 回退N帧协议(GBN)有差错情况下的详细流程
  • Unity2D 五子棋 + Photon联网双人对战
  • Android系统的安全问题 - Linux的能力模型(Capability)和 SELinux 的区别
  • Checksum方法实现
  • DDR4、DDR5、固态硬盘(SSD)和机械硬盘(HDD)在连续读/写、随机读/写性能的对比分析
  • Softmax 回归 + 损失函数 + 图片分类数据集
  • 重生细胞全符文获取攻略
  • LangChain4j(1):初识LangChain4j
  • 3. 轴指令(omron 机器自动化控制器)——>MC_GearInPos
  • Open CASCADE学习|根据给定的点集拟合一条B样条曲线
  • MATLAB导入Excel数据
  • 【论文精读-图像恢复】 All-In-One Image Restoration for Unknown Corruption
  • Kotlin 协程官方文档知识汇总(二)
  • MySQL 和 Redis 数据一致性解决方案
  • 字节码生成技术
  • springboot启动事件CommandLineRunner使用
  • HarmonyOS Next~鸿蒙应用框架开发实战:Ability Kit与Accessibility Kit深度解析
  • BFS专项练习 —— 蓝桥杯刷题
  • SICAR 标准 KUKA 机器人标准功能块说明手册