全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-20 8 分钟 ✍️ juanwangdev

变量与运行时上下文

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_ctxngx_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 连接一致

📝 发现内容有误?点击此处直接编辑

← 上一篇 内存池与数据结构
下一篇 → 模块编译与集成
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库