1. 内部变量:
-
preconfiguration阶段,调用ngx_http_variables_add_core_vars:
1)初始化cmcf->variables_keys结构体;
2)遍历ngx_http_core_variables核心变量数组,创建ngx_http_variable_t结构体作为value,变量名为key加入cmcf->variables_keys->keys数组,同时根据核心变量数组成员,为ngx_http_variable_t的其它成员,如set_handler、get_handler等赋值。 -
HTTP各模块配置解析阶段:
1)对于各模块中使用到的变量,如rewrite模块的set或rewrite指令,调用ngx_http_get_variable_index函数,创建ngx_http_variable_t结构体,加入cmcf->variables数组,此时结构体除name、index外的其他成员均未赋值。 -
HTTP各模块配置解析结束阶段(ngx_http_block->ngx_http_variables_init_vars):
1)变量cmcf->variables和cmcf->variables_keys->keys数组,对于两数组中都存在的成员进行关联,为前者赋值get_handler,为后者赋值index。
2)创建变量hash表。
2. 外部变量:
-
REWRITE模块配置解析阶段:
1)调用ngx_http_add_variable将变量加入cmcf->variables_keys->keys数组。
2)调用ngx_http_get_variable_index将变量加入cmcf->variables数组,获取index。
3)lcf->codes加入函数指针,用于将变量的实际值保存在栈中。
4)如果set的变量为内部变量,则lcf->codes加入函数指针,通过调用v->set_handler获得栈中变量值;如果set的变量为外部变量,则则lcf->codes加入函数指针(ngx_http_script_set_var_code),将栈中的变量值写入r->variables[]。 -
cmcf->variables_keys(ngx_hash_keys_arrays_t结构体)
cmcf->variables_keys->keys_hash:二维数组,一维代表name算出的hash,二维代表该hash下的所有name节点,该数组用于快速检索name是否存在冲突。
cmcf->variables_keys->keys:一维数组,节点包含name、key、value。
3. 变量获取
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_t flags;
ngx_uint_t index;
};
- get_handler:提供获取该变量值的方法,在业务阶段调用。
- set_handler:对于被重写的内部变量,在脚本执行(rewrite)阶段,通过该方法对变量值进行设置。
- flags :
//变量可被重写
#define NGX_HTTP_VAR_CHANGEABLE 1
//每次使用都需要通过get_handler重新获取,不可再请求中缓存
#define NGX_HTTP_VAR_NOCACHEABLE 2
//存在于cmcf->variables
#define NGX_HTTP_VAR_INDEXED 4
//该变量不加入hash表,即业务无法通过变量名获取变量值,只能通过index
#define NGX_HTTP_VAR_NOHASH 8
//不通过get函数获取值
#define NGX_HTTP_VAR_WEAK 16
//前缀型变量
#define NGX_HTTP_VAR_PREFIX 32 - index:在cmcf->variables中的编号
请求到来时,初始化
r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
* sizeof(ngx_http_variable_value_t));
该数组用于保存变量的缓存值。
调用
if (v[index].get_handler(r, &r->variables[index], v[index].data)
== NGX_OK)
对该请求某变量值进行获取,并在r->variables[index]缓存。
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;
获取变量值的接口
ngx_http_get_indexed_variable 通过index获取变量值,可能获取到r中的缓存
ngx_http_get_flushed_variable 通过index获取变量值,不获取缓存,重新调用get_handler
ngx_http_get_variable 通过变量名获取变量值,会查询hash表