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

ngx_http_core_location

定义在 src\http\ngx_http_core_module.c 

static char *
ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{char                      *rv;u_char                    *mod;size_t                     len;ngx_str_t                 *value, *name;ngx_uint_t                 i;ngx_conf_t                 save;ngx_http_module_t         *module;ngx_http_conf_ctx_t       *ctx, *pctx;ngx_http_core_loc_conf_t  *clcf, *pclcf;ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));if (ctx == NULL) {return NGX_CONF_ERROR;}pctx = cf->ctx;ctx->main_conf = pctx->main_conf;ctx->srv_conf = pctx->srv_conf;ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);if (ctx->loc_conf == NULL) {return NGX_CONF_ERROR;}for (i = 0; cf->cycle->modules[i]; i++) {if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {continue;}module = cf->cycle->modules[i]->ctx;if (module->create_loc_conf) {ctx->loc_conf[cf->cycle->modules[i]->ctx_index] =module->create_loc_conf(cf);if (ctx->loc_conf[cf->cycle->modules[i]->ctx_index] == NULL) {return NGX_CONF_ERROR;}}}clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];clcf->loc_conf = ctx->loc_conf;value = cf->args->elts;if (cf->args->nelts == 3) {len = value[1].len;mod = value[1].data;name = &value[2];if (len == 1 && mod[0] == '=') {clcf->name = *name;clcf->exact_match = 1;} else if (len == 2 && mod[0] == '^' && mod[1] == '~') {clcf->name = *name;clcf->noregex = 1;} else if (len == 1 && mod[0] == '~') {if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {return NGX_CONF_ERROR;}} else if (len == 2 && mod[0] == '~' && mod[1] == '*') {if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {return NGX_CONF_ERROR;}} else {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid location modifier \"%V\"", &value[1]);return NGX_CONF_ERROR;}} else {name = &value[1];if (name->data[0] == '=') {clcf->name.len = name->len - 1;clcf->name.data = name->data + 1;clcf->exact_match = 1;} else if (name->data[0] == '^' && name->data[1] == '~') {clcf->name.len = name->len - 2;clcf->name.data = name->data + 2;clcf->noregex = 1;} else if (name->data[0] == '~') {name->len--;name->data++;if (name->data[0] == '*') {name->len--;name->data++;if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {return NGX_CONF_ERROR;}} else {if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {return NGX_CONF_ERROR;}}} else {clcf->name = *name;if (name->data[0] == '@') {clcf->named = 1;}}}pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];if (cf->cmd_type == NGX_HTTP_LOC_CONF) {/* nested location */#if 0clcf->prev_location = pclcf;
#endifif (pclcf->exact_match) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"location \"%V\" cannot be inside ""the exact location \"%V\"",&clcf->name, &pclcf->name);return NGX_CONF_ERROR;}if (pclcf->named) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"location \"%V\" cannot be inside ""the named location \"%V\"",&clcf->name, &pclcf->name);return NGX_CONF_ERROR;}if (clcf->named) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"named location \"%V\" can be ""on the server level only",&clcf->name);return NGX_CONF_ERROR;}len = pclcf->name.len;#if (NGX_PCRE)if (clcf->regex == NULL&& ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)
#elseif (ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)
#endif{ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"location \"%V\" is outside location \"%V\"",&clcf->name, &pclcf->name);return NGX_CONF_ERROR;}}if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {return NGX_CONF_ERROR;}save = *cf;cf->ctx = ctx;cf->cmd_type = NGX_HTTP_LOC_CONF;rv = ngx_conf_parse(cf, NULL);*cf = save;return rv;
}

该函数是 Nginx 解析 location 配置块的核心实现,负责:

  1. 解析 location 语法 :支持精确匹配(=)、前缀匹配(^~)、正则表达式(~~*)及命名 location(@)。
  2. 创建配置上下文 :为当前 location 块初始化模块配置结构体。
  3. 管理嵌套规则 :确保 location 块的嵌套符合 Nginx 语法限制(如禁止在精确匹配或命名 location 内嵌套)。
  4. 注册 location 到父级配置 :将解析后的 location 添加到所属父级(server 或上层 location)的配置中。

    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));if (ctx == NULL) {return NGX_CONF_ERROR;}

 为 location 块创建独立的配置上下文 ,用于存储该作用域内的模块配置数据

ngx_http_conf_ctx_t -CSDN博客

    pctx = cf->ctx;ctx->main_conf = pctx->main_conf;ctx->srv_conf = pctx->srv_conf;

 继承父级配置上下文 ,确保 location 块可以复用父级(httpserver 块)的全局配置,同时允许独立覆盖或扩展自己的 loc_conf。 

  • main_conf :所有 location 共享同一份 http 配置。
  • srv_conf :同一 server 下的所有 location 共享 server 配置。
  • loc_conf :每个 location 独立,用于覆盖或扩展配置。
    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);if (ctx->loc_conf == NULL) {return NGX_CONF_ERROR;}

location 块的模块配置分配存储空间 ,确保每个 HTTP 模块可以在当前作用域(location)中存储自己的配置数据

    for (i = 0; cf->cycle->modules[i]; i++) {if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {continue;}module = cf->cycle->modules[i]->ctx;if (module->create_loc_conf) {ctx->loc_conf[cf->cycle->modules[i]->ctx_index] =module->create_loc_conf(cf);if (ctx->loc_conf[cf->cycle->modules[i]->ctx_index] == NULL) {return NGX_CONF_ERROR;}}}

 为每个 HTTP 模块初始化 location 级别的配置结构体 

    clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];clcf->loc_conf = ctx->loc_conf;

 将当前 location 的配置上下文(loc_conf 数组)关联到核心模块的配置结构体中 ,使得核心模块能够访问所有模块的配置数据,协调请求处理流程 

ngx_http_core_loc_conf_t-CSDN博客

    value = cf->args->elts;

获取指令的参数列表

    if (cf->args->nelts == 3) {
参数数量检查
  • cf->args->nelts
    表示当前配置指令(如 location)的参数数量。
    • nelts == 3 :用户使用了显式修饰符(如 location = /exact)。
    • nelts == 2 :用户未显式指定修饰符

此时 cf->args->nelts=2

条件不成立

进入 else 

else {name = &value[1];

获取 location 指令的第一个参数

此时 name->data=/

        if (name->data[0] == '=') {

 此时条件不成立

 

} else if (name->data[0] == '^' && name->data[1] == '~') {

此时 条件不成立

} else if (name->data[0] == '~') {

此时 条件不成立

 

        } else {clcf->name = *name;if (name->data[0] == '@') {clcf->named = 1;}}

namelocation 指令的路径参数(如 value[1],即用户配置中的第二个参数)。

将路径字符串赋值给核心模块配置结构体的 name 字段

此时 这里的 if 条件不成立

pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];

 获取父级 location 的核心模块配置 ,用于校验嵌套规则或继承配置

通过索引从父级的 loc_conf 数组中获取核心模块的配置结构体

指向父级 location 的核心模块配置结构体

if (cf->cmd_type == NGX_HTTP_LOC_CONF) {

判断当前是否处于 location 块的配置解析阶段

此时 cf->cmd_type=4000000      NGX_HTTP_LOC_CONF=8000000

条件不成立,当前还未进入 location 块内部配置解析的阶段

    if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {return NGX_CONF_ERROR;}

将新解析的 location 配置添加到父级(server 或上层 location)的链表中 ,确保请求处理时能够遍历所有 location 进行匹配。

  • ngx_http_add_location 函数 :
    • 功能 :将当前 locationclcf)添加到父级的 locations 链表(pclcf->locations)。
    • 参数 :
      • cf:配置解析上下文。
      • &pclcf->locations:父级的 locations 链表指针。
      • clcf:当前 location 的核心模块配置结构体。

locations 链表 :
存储所有 location 配置

ngx_http_add_location-CSDN博客 

    save = *cf;cf->ctx = ctx;cf->cmd_type = NGX_HTTP_LOC_CONF;rv = ngx_conf_parse(cf, NULL);*cf = save;

 

save = *cf;

  • 保存当前配置解析上下文。
  • 逻辑 :
    • cf 是指向当前配置解析上下文(ngx_conf_t 结构)的指针。
    • save 是一个局部变量,类型为 ngx_conf_t
    • 通过 *cf 解引用操作,将当前配置解析状态(包括上下文指针、命令类型等)完整复制到 save 中。
  • 意义 :
    • 在后续解析 location 块时,会临时修改 cf 的上下文。此操作保存原始状态,以便解析完成后恢复。

cf->ctx = ctx;

  • 作用 :切换配置上下文到当前 location 的上下文。
  • 逻辑 :
    • ctx 是新创建的 ngx_http_conf_ctx_t 结构,专用于当前 location 块。
    • cf->ctx 是配置解析的核心上下文指针,指向当前生效的配置存储结构。
    • cf->ctx 指向新的 ctx,使得后续解析的指令会将配置存储到该 location 的上下文中。

 cf->cmd_type = NGX_HTTP_LOC_CONF;

  • 作用 :设置当前解析的指令类型为 "HTTP Location 配置"。
  • 逻辑 :
    • cmd_typengx_conf_t 中的字段,用于标识当前解析的指令类型。
    • NGX_HTTP_LOC_CONF 表示接下来解析的指令属于 location 块。
  • 意义 :
    • 指令过滤 :Nginx 根据 cmd_type 调用对应模块的指令处理函数。例如,只有声明为 NGX_HTTP_LOC_CONF 类型的指令会被处理,其他指令(如 server 级指令)会触发错误。

rv = ngx_conf_parse(cf, NULL);

  • 作用 :解析 location 块内的配置指令。
  • 逻辑 :
    • ngx_conf_parse 是 Nginx 的核心配置解析函数。
    • 传入 cf(已切换到 location 上下文)和 NULL(表示继续解析当前配置流,而非新文件)。
    • 返回值 rv 表示解析结果(成功或错误码)。
  • 意义 :
    • 递归解析 :处理 location 块内的所有指令

ngx_conf_parse - location块-CSDN博客


*cf = save;

  • 作用 :恢复原始配置解析上下文。
  • 逻辑 :
    • 将之前保存的 save 值复制回 cf,覆盖当前修改后的 cf 状态。
    • 恢复字段包括 ctx(父级上下文)和 cmd_type(如 server 级指令类型)。
  • 意义 :
    • 上下文回退 :确保解析完当前 location 后,父级配置解析(如 server 块)能继续正确执行。
    • 避免污染 :防止 location 的临时配置影响后续指令的解析。

整体逻辑总结

  1. 保存现场 :备份父级配置上下文。
  2. 切换上下文 :为 location 块创建独立的配置存储空间。
  3. 标记指令类型 :确保仅处理 location 级指令。
  4. 解析子配置 :处理 location 内的所有指令。
  5. 恢复现场 :回到父级配置解析流程。
return rv;

返回 NGX_CONF_OK


http://www.mrgr.cn/news/95851.html

相关文章:

  • SVN常用命令
  • 团体协作项目总结Git
  • 基于Ebay拍卖网站成交价格的影响因素分析
  • python工厂模式
  • 2025前端面试题(vue、react、uniapp、微信小程序、JS、CSS、其他)
  • 吾爱出品,文件分类助手,高效管理您的 PC 资源库
  • 内核编程十二:打印task_struct中的数据
  • 单片机和微控制器知识汇总——《器件手册--单片机、数字信号处理器和可编程逻辑器件》
  • Mycat安装验证流程整理
  • 【Pandas】pandas Series to_csv
  • Vue 3 组件高级语法
  • 【c++入门系列】:引用以及内联函数详解
  • 【Golang】补充:占位符、转义字符、错误处理
  • Cucumber 专题系列 - 第三篇:编写第一个 Feature 文件
  • 轮回的起点与终点:一场跨越时空的哲学对话
  • 程序化广告行业(33/89):深入了解OTT、OTV及多样广告形式
  • 【精心整理】2025 DeepSeek 精品学习资料合集-共50份(教程+原理解读+行业应用+技术实践).zip
  • 36.评论日记
  • 【工程记录】QwQ-32b 8bit量化部署教程(vLLM | 缓解复读)
  • LVS的 NAT 模式实验