声明在 src\http\ngx_http_core_module.c
ngx_int_t ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
ngx_http_core_loc_conf_t *clcf);
定义在 src\http\ngx_http.c
ngx_int_t
ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
ngx_http_core_loc_conf_t *clcf)
{
ngx_http_location_queue_t *lq;
if (*locations == NULL) {
*locations = ngx_palloc(cf->temp_pool,
sizeof(ngx_http_location_queue_t));
if (*locations == NULL) {
return NGX_ERROR;
}
ngx_queue_init(*locations);
}
lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
if (lq == NULL) {
return NGX_ERROR;
}
if (clcf->exact_match
#if (NGX_PCRE)
|| clcf->regex
#endif
|| clcf->named || clcf->noname)
{
lq->exact = clcf;
lq->inclusive = NULL;
} else {
lq->exact = NULL;
lq->inclusive = clcf;
}
lq->name = &clcf->name;
lq->file_name = cf->conf_file->file.name.data;
lq->line = cf->conf_file->line;
ngx_queue_init(&lq->list);
ngx_queue_insert_tail(*locations, &lq->queue);
if (ngx_http_escape_location_name(cf, clcf) != NGX_OK) {
return NGX_ERROR;
}
return NGX_OK;
}
ngx_http_add_location
函数的作用是将一个新的 location 配置项添加到 Nginx 的 location 队列中,以便后续处理 HTTP 请求时进行匹配
ngx_int_t
ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
ngx_http_core_loc_conf_t *clcf)
{
ngx_http_location_queue_t *lq;
if (*locations == NULL) {
*locations = ngx_palloc(cf->temp_pool,
sizeof(ngx_http_location_queue_t));
if (*locations == NULL) {
return NGX_ERROR;
}
ngx_queue_init(*locations);
}
声明一个指向
ngx_http_location_queue_t
类型的指针lq
,用于后续存储新的 location 配置节点ngx_http_location_queue_t-CSDN博客
判断传入的locations
队列是否为空(未初始化)如果队列未初始化(
*locations == NULL
),需要为其分配内存并初始化队列结构此时 *locations=NULL
lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
if (lq == NULL) {
return NGX_ERROR;
}
为新的 location 队列节点分配内存
if (clcf->exact_match
#if (NGX_PCRE)
|| clcf->regex
#endif
|| clcf->named || clcf->noname)
{
lq->exact = clcf;
lq->inclusive = NULL;
} else {
lq->exact = NULL;
lq->inclusive = clcf;
}
clcf->exact_match
表示当前 location 是精确匹配 (如location = /exact/ {}
)。
clcf->regex
表示当前 location 使用正则表达式 (如location ~ ^/regex/ {}
)。
- 该条件受
NGX_PCRE
宏控制,仅在编译时启用 PCRE 库时生效。clcf->named
表示当前 location 是命名 location (如location @name {}
),通常用于内部跳转。clcf->noname
表示当前 location 是未命名的特殊 location (如location / {}
的默认配置)条件判断:
如果当前 location 是以下类型之一:
exact_match
(=
精确匹配)
regex
(正则表达式匹配,如~
或~*
)
named
(命名 location,如location @name
)
noname
(无名 location,如location {}
)则将其标记为
exact
类型(高优先级)。否则 (进入
else
分支),标记为inclusive
类型(普通前缀匹配)。字段赋值:
exact = NULL
:显式清空高优先级匹配指针。
inclusive = clcf
:将当前 location 的配置结构体指针赋给inclusive
,表示这是一个普通前缀匹配的 locationNginx 在路由请求时
按优先级顺序匹配(精确匹配 > 正则匹配 > 普通前缀匹配)
此时 exact_match=0 regex=NULL named=0 noname=0
lq->name = &clcf->name;
lq->file_name = cf->conf_file->file.name.data;
lq->line = cf->conf_file->line;
lq->name = &clcf->name;
- 作用 :将
lq
的name
指针指向当前 location 配置的名称(clcf->name
)。- 意义 :
clcf->name
是ngx_str_t
类型,存储了 location 的匹配规则(如/api
、~ ^/regex
)。- 通过
lq->name
可以直接访问该名称,用于请求匹配时的调试输出 或日志记录(例如记录命中了哪个 location)。
lq->file_name = cf->conf_file->file.name.data;
- 作用 :将
lq
的file_name
指向当前解析的配置文件路径(如/etc/nginx/conf.d/default.conf
)。- 意义 :
cf->conf_file->file.name.data
是一个字符串,表示当前解析的配置文件路径。- 在出现配置错误(如重复 location 或语法错误)时,Nginx 可以通过
file_name
定位到具体的配置文件,方便用户快速排查问题。
lq->line = cf->conf_file->line;
- 作用 :将
lq
的line
设置为当前解析的配置文件行号。- 意义 :
cf->conf_file->line
是一个整数,表示当前解析到的配置文件行号。- 结合
file_name
,可以在错误日志中精确标识配置的位置 (例如nginx.conf:15
),提升调试效率。
此时lq->name->data=/
lq->file_name=/home/wsd/桌面/nginx/conf/nginx.conf
lq->line=43
ngx_queue_init(&lq->list);
初始化
ngx_http_location_queue_t
节点内部的子队列若配置中存在嵌套的 location(如
location /parent { location /child {} }
),父 location 的list
可用于链接子节点
ngx_queue_insert_tail(*locations, &lq->queue);
将新节点添加到队列的末尾
if (ngx_http_escape_location_name(cf, clcf) != NGX_OK) {
return NGX_ERROR;
}
- 调用转义函数 :
ngx_http_escape_location_name(cf, clcf)
对clcf->name
(location 的名称)进行 URI 转义。- 错误检查 :
如果转义失败(返回值非NGX_OK
),立即终止当前配置解析,返回NGX_ERROR
return NGX_OK;
返回 NGX_OK