定义在 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