本文介绍了nginx变量的相关知识,在Nginx中同一个请求需要在模块之间数据的传递或者说在配置文件里面使用模块动态的数据一般来说都是使用变量,需要的朋友参考下。
一、变量概述
struct ngx_http_variable_s {
ngx_str_t name; /* must be first to build the hash */ ngx_http_set_variable_pt set_handler; ngx_http_get_variable_pt get_handler; uintptr_t data; ngx_uint_tflags; ngx_uint_tindex; }; 其中,name表示对应的变量名字,set/get_handler表示对应的设置以及读取回调,而data是传递给回调的参数,flags表示变量的属性,index提供了一个索引(数组的脚标),从而可以迅速定位到对应的变量,set/get_handler只有在真正读取设置变量的时候才会被调用。
二、nginx变量创建
ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags);
这个函数所做的工作就是将变量“name”添加进全局的hash key表中,然后初始化一些域。
var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
... //设置回调 var->get_handler = ngx_http_split_clients_variable; var->data = (uintptr_t) ctx;
而对应的回调函数原型如下:
typedef void (*ngx_http_set_variable_pt) (ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
typedef ngx_int_t (*ngx_http_get_variable_pt) (ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); 其中,第一个参数是当前请求,第二个是需要设置或者获取的变量值,第三个是初始化时的回调指针,这里我们着重来看一下ngx_http_variable_value_t,下面就是这个结构体的原型:
typedef struct {
unsigned len:28; unsigned valid:1; unsigned no_cacheable:1; unsigned not_found:1; unsigned escape:1; u_char *data; } ngx_variable_value_t;
这里重点是data域,在get_handle中设置变量值的时候,只需将对应的值放入到data中就可以了,data需要在get_handle中分配内存,举例说明如下:
v->len = f->script_name.len + flcf->index.len;
v->data = ngx_pnalloc(r->pool, v->len); ... p = ngx_copy(v->data, f->script_name.data, f->script_name.len); ngx_memcpy(p, flcf->index.data, flcf->index.len);
三、变量使用
ngx_int_t ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name);
2、取变量
ngx_http_variable_value_t *ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index);
ngx_http_variable_value_t *ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index); ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key);
前两者用来取得有索引的变量(二者区别是前一个会处理NGX_HTTP_VAR_NOCACHEABLE标记,即能cache变量值,后一个真好相反),而最后一个可以取得无索引的变量。
static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op, ngx_str_t *value)
{ ngx_int_t index; //得到变量的索引 index = ngx_http_get_variable_index(cf, value); if (index == NGX_ERROR) { return NGX_ERROR; } op->len = 0; op->getlen = ngx_http_log_variable_getlen; op->run = ngx_http_log_variable; //保存索引值 op->data = index; return NGX_OK; }
然后http_log模块会使用ngx_http_get_indexed_variable来得到对应的变量值。注意:使用这个接口的时候,不仅要判断返回值是否为空,还需要判断value->not_found,因为只有第一次调用才会返回空,后续返回就不是空,因此需要判断value->not_found:
复制代码代码示例:
static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
{ ngx_http_variable_value_t *value; //获取变量值 value = ngx_http_get_indexed_variable(r, op->data); if (value == NULL || value->not_found) { *buf = '-'; return buf + 1; } if (value->escape == 0) { return ngx_cpymem(buf, value->data, value->len); } else { return (u_char *) ngx_http_log_escape(buf, value->data, value->len); } }
四、小技巧
7、父子请求 |