ngx_http_compile_complex_value
定义在 src\http\ngx_http_script.c
ngx_int_t
ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
{
ngx_str_t *v;
ngx_uint_t i, n, nv, nc;
ngx_array_t flushes, lengths, values, *pf, *pl, *pv;
ngx_http_script_compile_t sc;
v = ccv->value;
nv = 0;
nc = 0;
for (i = 0; i < v->len; i++) {
if (v->data[i] == '$') {
if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
nc++;
} else {
nv++;
}
}
}
if ((v->len == 0 || v->data[0] != '$')
&& (ccv->conf_prefix || ccv->root_prefix))
{
if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
return NGX_ERROR;
}
ccv->conf_prefix = 0;
ccv->root_prefix = 0;
}
ccv->complex_value->value = *v;
ccv->complex_value->flushes = NULL;
ccv->complex_value->lengths = NULL;
ccv->complex_value->values = NULL;
if (nv == 0 && nc == 0) {
return NGX_OK;
}
n = nv + 1;
if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
!= NGX_OK)
{
return NGX_ERROR;
}
n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
+ sizeof(ngx_http_script_var_code_t))
+ sizeof(uintptr_t);
if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
return NGX_ERROR;
}
n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
+ sizeof(ngx_http_script_var_code_t))
+ sizeof(uintptr_t)
+ v->len
+ sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1);
if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
return NGX_ERROR;
}
pf = &flushes;
pl = &lengths;
pv = &values;
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
sc.cf = ccv->cf;
sc.source = v;
sc.flushes = &pf;
sc.lengths = &pl;
sc.values = &pv;
sc.complete_lengths = 1;
sc.complete_values = 1;
sc.zero = ccv->zero;
sc.conf_prefix = ccv->conf_prefix;
sc.root_prefix = ccv->root_prefix;
if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_ERROR;
}
if (flushes.nelts) {
ccv->complex_value->flushes = flushes.elts;
ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
}
ccv->complex_value->lengths = lengths.elts;
ccv->complex_value->values = values.elts;
return NGX_OK;
}
该函数用于将 Nginx 配置中的动态字符串(包含变量或特殊符号)编译为可运行时解析的内部结构 ,以支持后续高效地生成实际值
v = ccv->value;
nv = 0;
nc = 0;
for (i = 0; i < v->len; i++) {
if (v->data[i] == '$') {
if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
nc++;
} else {
nv++;
}
}
}
v = ccv->value;
获取待编译的字符串值
nv = 0;
初始化变量计数器
nv
(variable count):统计普通变量(如$var
)的数量
nc = 0;
初始化变量计数器
nc
(capture count):统计正则捕获组变量(如$1
-9
)的数量
for (i = 0; i < v->len; i++) { ... }
遍历字符串的每个字符,逐个分析是否为变量
if (v->data[i] == '$') { ... }
检测变量起始符
$
如果当前字符是
$
,则进入变量分析逻辑变量以
$
开头,需进一步判断是普通变量还是正则捕获组
此次 没有符合条件的值
循环结束后
nv=0 nc=0
if ((v->len == 0 || v->data[0] != '$')
&& (ccv->conf_prefix || ccv->root_prefix))
{
if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
return NGX_ERROR;
}
ccv->conf_prefix = 0;
ccv->root_prefix = 0;
}
if ((v->len == 0 || v->data[0] != '$') && (ccv->conf_prefix || ccv->root_prefix))
v->len == 0
:检查字符串是否为空。v->data[0] != '$'
:检查字符串是否以$
开头(即是否为变量)ccv->conf_prefix || ccv->root_prefix
:检查是否需要添加前缀(配置路径或根路径)当字符串是静态路径 (非变量、非空)且需要路径前缀时,进入处理逻辑
ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix)
将相对路径转换为绝对路径
此次
v->len =9
v->data[0]=/
ccv->conf_prefix=0
ccv->root_prefix=0条件不成立
ccv->complex_value->value = *v;
ccv->complex_value->flushes = NULL;
ccv->complex_value->lengths = NULL;
ccv->complex_value->values = NULL;
ccv->complex_value->value = *v;
保存原始字符串值
v
是经过路径处理后的字符串
ccv->complex_value->flushes = NULL;
初始化
需要清除缓存的变量索引列表
ccv->complex_value->lengths = NULL;
初始化
lengths
指针
lengths
存储计算动态值长度的指令数组
ccv->complex_value->values = NULL;
初始化
values
指针
values
存储生成动态值内容的指令数组
ngx_http_complex_value_t-CSDN博客
if (nv == 0 && nc == 0) {
return NGX_OK;
}
条件成立
返回 NGX_OK