1 定义
ngx_http_escape_location_name 函数 定义在 ./nginx-1.24.0/src/http/ngx_http.c
staticngx_int_tngx_http_escape_location_name(ngx_conf_t*cf,ngx_http_core_loc_conf_t*clcf){u_char*p;size_tlen;uintptr_tescape;escape=2*ngx_escape_uri(NULL,clcf->name.data,clcf->name.len,NGX_ESCAPE_URI);if(escape){len=clcf->name.len+escape;p=ngx_pnalloc(cf->pool,len);if(p==NULL){returnNGX_ERROR;}clcf->escaped_name.len=len;clcf->escaped_name.data=p;ngx_escape_uri(p,clcf->name.data,clcf->name.len,NGX_ESCAPE_URI);}else{clcf->escaped_name=clcf->name;}returnNGX_OK;}
ngx_http_escape_location_name 函数的作用是 在配置加载阶段对 `location` 的名称进行 URI 转义, 将结果存入 `clcf->escaped_name`。 它通过先计算所需长度再分配内存的方式高效生成合法 URI, 用于后续重定向或内部跳转,确保 URL 符合规范且避免安全风险。
2 详解
1 函数签名
staticngx_int_tngx_http_escape_location_name(ngx_conf_t*cf,ngx_http_core_loc_conf_t*clcf)
返回值 表示函数执行结果的状态码 NGX_OK:转义操作成功(包括无需转义直接复用原始名称的情况)。 NGX_ERROR:内存分配失败,配置加载过程应中止。
参数1 ngx_conf_t *cf 配置解析时的全局上下文
参数2 ngx_http_core_loc_conf_t *clcf 代表某个 location 块的 HTTP 核心模块配置。 输入与输出: 输入:clcf->name(ngx_str_t 类型) 是配置文件中 location 后未经转义的原始名称 输出:函数会修改 clcf->escaped_name(ngx_str_t 类型), 将其设置为转义后的字符串(可能需要重新分配内存), 或者直接指向原始 name(当无需转义时)。
2 逻辑流程
1 局部变量 2 转义处理 3 返回成功
1 局部变量
{u_char*p;size_tlen;uintptr_tescape;
escape=2*ngx_escape_uri(NULL,clcf->name.data,clcf->name.len,NGX_ESCAPE_URI);
计算需要转义的增加长度 ngx_escape_uri 函数: 当第一个参数为 NULL 时,它不会实际写入转义结果, 而是返回需要转义的字符个数(即原始字符串中需要被编码的字符数量)。 每个需要转义的字符将由原来的 1 个字节变为 3 个字节(%XX), 因此总长度增加量为 2 × 转义字符数。 NGX_ESCAPE_URI: 转义模式,对 URI 中除保留字符外的非字母数字字符进行百分号编码。 作用:获取转义后需要增加的字节数,为后续精确内存分配做准备。 意义:采用先计算再分配的策略
2 转义处理
if(escape){len=clcf->name.len+escape;p=ngx_pnalloc(cf->pool,len);if(p==NULL){returnNGX_ERROR;}clcf->escaped_name.len=len;clcf->escaped_name.data=p;ngx_escape_uri(p,clcf->name.data,clcf->name.len,NGX_ESCAPE_URI);}else{clcf->escaped_name=clcf->name;}
判断是否需要转义 escape != 0 表示原始名称中包含需要转义的字符,必须生成新字符串; 若为 0,则名称完全符合 URI 规范,无需转义。
#1 计算转义后的总长度 原始长度加上需要增加的长度,得到转义后字符串的总字节数。
从配置内存池分配内存 设置 escaped_name 的长度和数据指针
ngx_escape_uri 执行真正的转义并写入内存
#2 无需转义时的处理 如果 escape == 0,说明原始名称完全合法, 直接将 escaped_name 指向 name, 共享同一块内存,避免任何分配和拷贝开销。
3 返回成功
returnNGX_OK;}