变量与运行时上下文
Nginx 变量系统支持配置引用和运行时数据获取,变量值惰性求值,通过索引实现高效查找。
变量注册机制
变量定义
C
static ngx_http_variable_t ngx_http_my_vars[] = {
{ ngx_string("my_var"), NULL, ngx_http_my_var_handler,
0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
{ ngx_string("my_param"), NULL, ngx_http_my_param_handler,
offsetof(ngx_http_my_conf_t, param), NGX_HTTP_VAR_NOCACHEABLE, 0 },
ngx_http_null_variable
};
变量注册
C
static ngx_int_t
ngx_http_my_add_variables(ngx_conf_t *cf)
{
ngx_http_variable_t *v;
for (v = ngx_http_my_vars; v->name.len; v++) {
ngx_http_variable_t *var;
var = ngx_http_add_variable(cf, &v->name, v->flags);
if (var == NULL) {
return NGX_ERROR;
}
var->get_handler = v->get_handler;
var->data = v->data;
}
return NGX_OK;
}
变量通过
ngx_http_add_variable注册到全局变量索引表,返回变量索引供后续查找使用。
变量标志位
| 标志位 | 说明 |
|---|---|
| NGX_HTTP_VAR_CHANGEABLE | 值可被修改 |
| NGX_HTTP_VAR_NOCACHEABLE | 不缓存,每次重新计算 |
| NGX_HTTP_VAR_INDEXED | 使用索引加速查找 |
| NGX_HTTP_VAR_NOHASH | 不加入哈希表 |
变量处理函数
简单变量
C
static ngx_int_t
ngx_http_my_var_handler(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_str_t value;
value.len = 10;
value.data = ngx_pnalloc(r->pool, value.len);
if (value.data == NULL) {
return NGX_ERROR;
}
ngx_memcpy(value.data, "my_value", 8);
v->len = value.len;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = value.data;
return NGX_OK;
}
复杂变量(依赖请求上下文)
C
static ngx_int_t
ngx_http_my_header_var(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_str_t *name = (ngx_str_t *) data;
ngx_uint_t i;
// 查找请求头
ngx_list_part_t *part = &r->headers_in.headers.part;
ngx_table_elt_t *headers = part->elts;
for (i = 0; /* void */; i++) {
if (i >= part->nelts) {
if (part->next == NULL) break;
part = part->next;
headers = part->elts;
i = 0;
}
if (ngx_strncasecmp(headers[i].key.data, name->data, name->len) == 0) {
v->len = headers[i].value.len;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = headers[i].value.data;
return NGX_OK;
}
}
v->not_found = 1;
return NGX_OK;
}
变量查找流程
C
配置中引用变量 $var
→ ngx_http_get_variable_index() 获取变量索引
→ 请求处理时 ngx_http_get_flushed_variable(r, index)
→ 查找变量定义
→ 调用 get_handler 获取值
→ 返回变量值
获取变量值
C
// 编译时获取索引
ngx_int_t index = ngx_http_get_variable_index(cf, &var_name);
// 运行时获取值
ngx_http_variable_value_t *val = ngx_http_get_indexed_variable(r, index);
if (val && !val->not_found) {
// 使用 val->data, val->len
}
运行时上下文
请求级上下文
C
typedef struct {
ngx_str_t my_data;
ngx_int_t my_status;
ngx_http_my_conf_t *conf;
} ngx_http_my_ctx_t;
// 创建上下文
static ngx_int_t
ngx_http_my_handler(ngx_http_request_t *r)
{
ngx_http_my_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_my_module);
if (ctx == NULL) {
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_my_ctx_t));
if (ctx == NULL) {
return NGX_ERROR;
}
ngx_http_set_module_ctx(r, ctx, ngx_http_my_module);
}
ctx->my_status = 1;
return NGX_OK;
}
请求上下文使用
ngx_http_get_module_ctx和ngx_http_set_module_ctx管理,生命周期与请求一致。
连接级上下文
text
typedef struct {
ngx_http_my_session_t *session;
ngx_connection_t *connection;
} ngx_http_my_connection_ctx_t;
c->data = my_conn_ctx; // 存储连接级数据
要点总结
- 变量通过
ngx_http_add_variable注册,惰性求值,支持缓存和非缓存模式 - 变量处理函数接收
ngx_http_variable_value_t结构,设置 valid/not_found 标志 - 变量查找分两步:编译时获取索引,运行时通过索引获取值
- 请求上下文通过
ngx_http_get_module_ctx/ngx_http_set_module_ctx管理 - 连接上下文存储在
c->data,生命周期与 TCP 连接一致
📝 发现内容有误?点击此处直接编辑