nginx http變量定義
struct ngx_http_variable_s {ngx_str_t ? ? ? ? ? ? ? ? ? ? name; ? //變量名ngx_http_set_variable_pt ? ? ?set_handler; ?//設(shè)置變量函數(shù)ngx_http_get_variable_pt ? ? ?get_handler; ?//獲取變量函數(shù)uintptr_t ? ? ? ? ? ? ? ? ? ? data; ? //變量中的數(shù)據(jù)ngx_uint_t ? ? ? ? ? ? ? ? ? ?flags; ?//變量標(biāo)志ngx_uint_t ? ? ? ? ? ? ? ? ? ?index; ?//變量索引值
}
正則變量
typedef struct {ngx_uint_t ? ? ? ? ? ? ? ? ? ?capture;?ngx_int_t ? ? ? ? ? ? ? ? ? ? index;
} ngx_http_regex_variable_t
?
typedef struct {ngx_regex_t ? ? ? ? ? ? ? ? ?*regex; ? ? ? ?//正則表達(dá)式ngx_uint_t ? ? ? ? ? ? ? ? ? ?ncaptures; ? ?//俘獲的正則變量數(shù)量ngx_http_regex_variable_t ? ?*variables; ? ?//正則變量表ngx_uint_t ? ? ? ? ? ? ? ? ? ?nvariables; ? //正則變量數(shù)量ngx_str_t ? ? ? ? ? ? ? ? ? ? name; ? ? ? ? //正則變量名
} ngx_http_regex_t
?
typedef struct {ngx_http_regex_t ? ? ? ? ? ? *regex; ? ? ?//正則表達(dá)式void ? ? ? ? ? ? ? ? ? ? ? ? *value; ? ? ?//正則值
} ngx_http_map_regex_t
正則字典
typedef struct {ngx_hash_combined_t ? ? ? ? ? hash; ? ? ?//hash表
#if (NGX_PCRE)ngx_http_map_regex_t ? ? ? ? *regex; ? ? //正則表ngx_uint_t ? ? ? ? ? ? ? ? ? ?nregex; ? ?//元素數(shù)量
#endif
} ngx_http_map_t
變量值定義
typedef struct {unsigned ? ?len:28; ? ? ? ? ?//變量的長度unsigned ? ?valid:1; ? ? ? ? //valid 表示變量是否有效的標(biāo)記unsigned ? ?no_cacheable:1; ?//表示變量可否緩存unsigned ? ?not_found:1; ? ? //表示沒找到變量的值unsigned ? ?escape:1; ? ? ? ?//變量中是否有空格u_char ? ? *data; ? ? ? ? ? ?//變量數(shù)據(jù)
} ngx_variable_value_t
nginx變量類型
NGX_HTTP_VAR_CHANGEABLE ? ? //可變變量
NGX_HTTP_VAR_NOCACHEABLE ? ?//不可變變量
NGX_HTTP_VAR_INDEXED ? ? ? ?
NGX_HTTP_VAR_NOHASH
NGX_HTTP_VAR_PREFIX
nginx http變量原理及使用?
1.添加http變量(普通變量)
ngx_http_variable_t *
ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
{
...if (name->len == 0) {/*變量名為空,認(rèn)定無效同時返回錯誤*/ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid variable name \"$\"");return NULL;}if (flags & NGX_HTTP_VAR_PREFIX) {/*flags為前綴標(biāo)記 加入到前綴變量中*/return ngx_http_add_prefix_variable(cf, name, flags);}/*獲取main作用域的配置*/cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);/*main作用域配置的變量表*/key = cmcf->variables_keys->keys.elts;for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) {if (name->len != key[i].key.len|| ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0){ ?/*不在main作用域的變量表中*/continue;}/*獲取變量的key值*/v = key[i].value;if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {/*變量帶有changeable標(biāo)記 判定變量出現(xiàn)了重復(fù) 隨即返回空值*/ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"the duplicate \"%V\" variable", name);return NULL;}/*清除掉flags中的weak標(biāo)記*/v->flags &= flags | ~NGX_HTTP_VAR_WEAK;return v;}/*分配變量內(nèi)存*/v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));if (v == NULL) {/*可用內(nèi)存不足 返回空值*/return NULL;}/*拷貝變量名*/v->name.len = name->len;v->name.data = ngx_pnalloc(cf->pool, name->len);if (v->name.data == NULL) {return NULL;}//變量名小寫處理ngx_strlow(v->name.data, name->data, name->len);/*變量成員初始化*/v->set_handler = NULL;v->get_handler = NULL;v->data = 0;v->flags = flags;v->index = 0;/*將變量添加到 variable_keys集合中*/rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0);if (rc == NGX_ERROR) {/*添加失敗 返回空值*/return NULL;}if (rc == NGX_BUSY) {/*變量名與variables_keys集合中的變量出現(xiàn)了重復(fù)*/ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"conflicting variable name \"%V\"", name);return NULL;}/*返回新增的變量*/return v;
}
2.添加prefix[前綴]變量
static ngx_http_variable_t *
ngx_http_add_prefix_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
{
...//得到前綴變量表v = cmcf->prefix_variables.elts;for (i = 0; i < cmcf->prefix_variables.nelts; i++) {if (name->len != v[i].name.len|| ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0){ ? /*沒找到 跳過*/continue;}v = &v[i];if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {/*同普通變量處理*/ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"the duplicate \"%V\" variable", name);return NULL;}v->flags &= flags | ~NGX_HTTP_VAR_WEAK;return v;}/*添加到prefix_variables變量表中*/v = ngx_array_push(&cmcf->prefix_variables);if (v == NULL) {return NULL;}v->name.len = name->len;v->name.data = ngx_pnalloc(cf->pool, name->len);if (v->name.data == NULL) {return NULL;}ngx_strlow(v->name.data, name->data, name->len);/*變量初始化*/v->set_handler = NULL;v->get_handler = NULL;v->data = 0;v->flags = flags;v->index = 0;return v;
}
3.通過變量名獲取變量的index索引值
ngx_int_t
ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
{if (name->len == 0) {/*傳入的變量名是空的 返回錯誤*/ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid variable name \"$\"");return NGX_ERROR;}/*得到main作用域的變量表*/v = cmcf->variables.elts;if (v == NULL) {/*發(fā)現(xiàn)變量表為空 則創(chuàng)建一個變量表 默認(rèn)有4個元素*/if (ngx_array_init(&cmcf->variables, cf->pool, 4,sizeof(ngx_http_variable_t))!= NGX_OK){return NGX_ERROR;}} else {/*變量表存在 則在變量表中進(jìn)行查找*/for (i = 0; i < cmcf->variables.nelts; i++) {if (name->len != v[i].name.len|| ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0){ ?/*變量名不匹配 跳過*/continue;}//找到了變量return i;}}/*發(fā)現(xiàn)變量表中沒有這個變量 則將變量加入到變量表中*/v = ngx_array_push(&cmcf->variables);if (v == NULL) {//添加失敗 則返回錯誤return NGX_ERROR;}/*拷貝變量名稱到變量表中*/v->name.len = name->len;v->name.data = ngx_pnalloc(cf->pool, name->len);if (v->name.data == NULL) {return NGX_ERROR;}ngx_strlow(v->name.data, name->data, name->len);//初始化變量v->set_handler = NULL;v->get_handler = NULL;v->data = 0;v->flags = 0;v->index = cmcf->variables.nelts - 1;//返回變量的索引值(即在變量數(shù)組中的序號)return v->index;
}
3.通過變量的索引值獲取變量值
ngx_http_variable_value_t *
ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
{if (cmcf->variables.nelts <= index) {/*使用的索引值超過了數(shù)組的范圍 返回空值*/ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,"unknown variable index: %ui", index);return NULL;}if (r->variables[index].not_found || r->variables[index].valid) {/*變量not_found或者valid為真 直接返回變量值*/return &r->variables[index];}/*獲取配置的變量數(shù)組*/v = cmcf->variables.elts;if (ngx_http_variable_depth == 0) {/*如果變量的深度為0 表明變量的值正在進(jìn)行刷新 返回空值*/ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,"cycle while evaluating variable \"%V\"",&v[index].name);return NULL;}/*減少一次變量深度*/ngx_http_variable_depth--;if (v[index].get_handler(r, &r->variables[index], v[index].data)== NGX_OK){ ?/*獲取變量ok 增加一次變量深度*/ngx_http_variable_depth++;if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) {/*變量本身是nocacheable標(biāo)記 則重新加上 (以防在get函數(shù)中被修改)*/r->variables[index].no_cacheable = 1;}/*返回變量*/return &r->variables[index];}?/*獲取變量出錯 *///增加一次變量深度ngx_http_variable_depth++;/*?valid設(shè)置為假 not_found設(shè)置為真?valid表明變量無效 not_found表示沒找到變量的值?在下次調(diào)用中能復(fù)用還未刷新的變量值*/r->variables[index].valid = 0;r->variables[index].not_found = 1;return NULL;
}
4.獲取刷新的變量值
ngx_http_variable_value_t *
ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
{/*通過index索引找到變量值*/v = &r->variables[index];if (v->valid || v->not_found) {/*變量值是valid有效的或者是not_found標(biāo)記 */if (!v->no_cacheable) {/*如果變量值可以緩存 返回變量值*/return v;}/*重置 valid和not_found標(biāo)記 以通過get函數(shù)獲取變量 即刷新變量的作用*/v->valid = 0;v->not_found = 0;}/*通過3中的函數(shù)來取得變量的值*/return ngx_http_get_indexed_variable(r, index);
}
5.通過變量名及key值取得變量值
ngx_http_variable_value_t *
ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
{
...?/*在配置的變量表中取得變量 這兒使用hash值和名字來取得變量的*/v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);if (v) {/*找到了變量 */if (v->flags & NGX_HTTP_VAR_INDEXED) {return ngx_http_get_flushed_variable(r, v->index);}/*發(fā)現(xiàn)變量的深度為0 注意變量深度是全局靜態(tài)變量 針對所有請求而言意味著變量正在進(jìn)行“刷新” 此時返回空值*/if (ngx_http_variable_depth == 0) {ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,"cycle while evaluating variable \"%V\"", name);return NULL;}/*減少變量深度*/ngx_http_variable_depth--;/*為變量值分配空間*/vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));/*通過變量綁定的get函數(shù)計算得到變量的值*/if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {//成功獲得變量 ?增加一次變量深度ngx_http_variable_depth++;return vv;}//出錯 增加一次變量深度并且返回空值ngx_http_variable_depth++;return NULL;}/*為變量值分配空間*/vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));if (vv == NULL) {/*分配出錯 返回空值*/return NULL;}len = 0;/*在variables_hash中沒有找到變量 則從prefix_variables變量表中查找*/v = cmcf->prefix_variables.elts;n = cmcf->prefix_variables.nelts;for (i = 0; i < cmcf->prefix_variables.nelts; i++) {if (name->len >= v[i].name.len && name->len > len&& ngx_strncmp(name->data, v[i].name.data, v[i].name.len) == 0){ ?/*查找到變量 取得變量名的長度和索引值*/len = v[i].name.len;n = i;}}/*索引值在prefix_variables變量表的范圍之內(nèi) 則通過綁定的get函數(shù)取得變量值*/if (n != cmcf->prefix_variables.nelts) {if (v[n].get_handler(r, vv, (uintptr_t) name) == NGX_OK) {return vv;}/*獲取變量出錯 返回空值*/return NULL;}/*沒有找到變量 not_found為真 返回變量值*/vv->not_found = 1;return vv;
}
6.獲取http請求的變量
static ngx_int_t
ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,uintptr_t data)
{ngx_str_t ?*s;/*通過成員在ngx_http_request_t結(jié)構(gòu)中的偏移計算得到成員的地址*/s = (ngx_str_t *) ((char *) r + data); ?if (s->data) {?/*成員有數(shù)據(jù) 得到數(shù)據(jù)*/v->len = s->len;v->valid = 1;v->no_cacheable = 0;v->not_found = 0;v->data = s->data;} else {//成員中沒有數(shù)據(jù) 進(jìn)行not_found標(biāo)記v->not_found = 1;}return NGX_OK;
}
7.獲取http_request_t成員中的“大小”類型的變量
static ngx_int_t
ngx_http_variable_request_get_size(ngx_http_request_t *r,ngx_http_variable_value_t *v, uintptr_t data)
{size_t ?*sp;/*通過結(jié)構(gòu)體的偏移得到 地址*/sp = (size_t *) ((char *) r + data);/*為變量值分配空間*/v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);if (v->data == NULL) {//分配失敗 返回錯誤return NGX_ERROR;}/*拷貝數(shù)據(jù)到 變量值中*/v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;v->valid = 1;v->no_cacheable = 0;v->not_found = 0;return NGX_OK;
}
8.通過變量值設(shè)置http_request_t中的長度成員值
static void
ngx_http_variable_request_set_size(ngx_http_request_t *r,ngx_http_variable_value_t *v, uintptr_t data)
{
...//得到變量的長度及數(shù)據(jù)信息 ? ?val.len = v->len;val.data = v->data;/*解析字符串得到“長度”大小*/s = ngx_parse_size(&val);if (s == NGX_ERROR) {/*解析失敗 報錯*/ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,"invalid size \"%V\"", &val);return;}/*取得位于結(jié)構(gòu)體中的地址*/sp = (ssize_t *) ((char *) r + data);/* *引用取得值 并進(jìn)行設(shè)置 內(nèi)存地址無變化*/*sp = s;return;
}
9.獲得http頭變量的值
static ngx_int_t
ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,uintptr_t data)
{ngx_table_elt_t ?*h;/*通過結(jié)構(gòu)體中的成員的偏移得到 hash表的元素*/h = *(ngx_table_elt_t **) ((char *) r + data);?if (h) {/*存在 則取得元素的值 并設(shè)置到變量中*/v->len = h->value.len;v->valid = 1;v->no_cacheable = 0;v->not_found = 0;v->data = h->value.data;} else {/*不存在 進(jìn)行not_found標(biāo)記*/v->not_found = 1;}return NGX_OK;
}
10.添加ngx_http_core_module中的變量
ngx_int_t
ngx_http_variables_add_core_vars(ngx_conf_t *cf)
{
...cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);/*為ngx_http_core_module的變量分配空間*/cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,sizeof(ngx_hash_keys_arrays_t));if (cmcf->variables_keys == NULL) {/*分配失敗 返回錯誤*/return NGX_ERROR;}/*內(nèi)存池設(shè)置*/cmcf->variables_keys->pool = cf->pool;cmcf->variables_keys->temp_pool = cf->pool;/*初始化variables_keys hash表*/if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL)!= NGX_OK){return NGX_ERROR;}/*初始化prefix_variables數(shù)組*/if (ngx_array_init(&cmcf->prefix_variables, cf->pool, 8,sizeof(ngx_http_variable_t))!= NGX_OK){return NGX_ERROR;}/*添加http core變量 注意cv取得的是指針數(shù)組*/for (cv = ngx_http_core_variables; cv->name.len; cv++) {v = ngx_http_add_variable(cf, &cv->name, cv->flags);if (v == NULL) {/*變量添加失敗 返回錯誤*/return NGX_ERROR;}/*設(shè)置變量值*/*v = *cv;}return NGX_OK;
}
初始化配置的變量
ngx_int_t
ngx_http_variables_init_vars(ngx_conf_t *cf)
{
...cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);/*取得core_module的變量數(shù)組*/v = cmcf->variables.elts;/*取得prefix_variables變量數(shù)組*/pv = cmcf->prefix_variables.elts;/*取得variables_keys數(shù)組*/key = cmcf->variables_keys->keys.elts;for (i = 0; i < cmcf->variables.nelts; i++) {for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {av = key[n].value;if (v[i].name.len == key[n].key.len&& ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)/*在variables hash表中找到了變量*/== 0){/*設(shè)置變量的get函數(shù) 及回調(diào)參數(shù)*/v[i].get_handler = av->get_handler;v[i].data = av->data;/*將變量標(biāo)記為 INDEXED*/av->flags |= NGX_HTTP_VAR_INDEXED;/*設(shè)置變量的flags標(biāo)記*/v[i].flags = av->flags;//設(shè)置變量的索引值av->index = i;/*變量沒有設(shè)置get函數(shù)或者變量為weak標(biāo)記(即不通過get進(jìn)行獲取)跳出循環(huán)*/if (av->get_handler == NULL|| (av->flags & NGX_HTTP_VAR_WEAK)){break;}goto next;}}/*在variables_keys hash表中沒有找到變量在prefix_variables表中查找變量*/len = 0;av = NULL;for (n = 0; n < cmcf->prefix_variables.nelts; n++) {if (v[i].name.len >= pv[n].name.len && v[i].name.len > len&& ngx_strncmp(v[i].name.data, pv[n].name.data, pv[n].name.len)== 0){ ? /*找到了變量 取得變量和變量名的長度*/av = &pv[n];len = pv[n].name.len;}}if (av) {/*變量存在 設(shè)置變量的get函數(shù)及回調(diào)參數(shù)以及flags*/v[i].get_handler = av->get_handler;v[i].data = (uintptr_t) &v[i].name;v[i].flags = av->flags;/*完成*/goto next;}if (v[i].get_handler == NULL) {/*發(fā)現(xiàn)沒有g(shù)et函數(shù) 報錯并且返回錯誤*/ngx_log_error(NGX_LOG_EMERG, cf->log, 0,"unknown \"%V\" variable", &v[i].name);return NGX_ERROR;}next:continue;}for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {av = key[n].value;if (av->flags & NGX_HTTP_VAR_NOHASH) {/*對于不使用hash進(jìn)行索引查找的變量 將key值置為空值*/key[n].key.data = NULL;}}/*hash表進(jìn)行初始化*/hash.hash = &cmcf->variables_hash;hash.key = ngx_hash_key;hash.max_size = cmcf->variables_hash_max_size;hash.bucket_size = cmcf->variables_hash_bucket_size;hash.name = "variables_hash";hash.pool = cf->pool;hash.temp_pool = NULL;/*將vaiables_keys數(shù)據(jù)拷貝到 hash表中*/if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts,cmcf->variables_keys->keys.nelts)!= NGX_OK){return NGX_ERROR;}/*將variables_keys hash表賦值為空 并且返回*/cmcf->variables_keys = NULL;return NGX_OK;
}
---------------------?
作者:huzilinitachi?
來源:CSDN?
原文:https://blog.csdn.net/huzilinitachi/article/details/79902950?
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!
超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生
總結(jié)
以上是生活随笔為你收集整理的nginx处理http(http变量篇)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。