nginx http变量定义

struct ngx_http_variable_s {ngx_str_t                     name;   //变量名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;  //变量索引值
}

正则变量

typedef struct {ngx_uint_t                    capture; ngx_int_t                     index;
} ngx_http_regex_variable_t
typedef struct {ngx_regex_t                  *regex;        //正则表达式ngx_uint_t                    ncaptures;    //俘获的正则变量数量ngx_http_regex_variable_t    *variables;    //正则变量表ngx_uint_t                    nvariables;   //正则变量数量ngx_str_t                     name;         //正则变量名
} ngx_http_regex_t
typedef struct {ngx_http_regex_t             *regex;      //正则表达式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;    //元素数量
#endif
} ngx_http_map_t

变量值定义

typedef struct {unsigned    len:28;          //变量的长度unsigned    valid:1;         //valid 表示变量是否有效的标记unsigned    no_cacheable:1;  //表示变量可否缓存unsigned    not_found:1;     //表示没找到变量的值unsigned    escape:1;        //变量中是否有空格u_char     *data;            //变量数据
} 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) {/*变量名为空,认定无效同时返回错误*/ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid variable name \"$\"");return NULL;}if (flags & NGX_HTTP_VAR_PREFIX) {/*flags为前缀标记 加入到前缀变量中*/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标记 判定变量出现了重复 随即返回空值*/ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"the duplicate \"%V\" variable", name);return NULL;}/*清除掉flags中的weak标记*/v->flags &= flags | ~NGX_HTTP_VAR_WEAK;return v;}/*分配变量内存*/v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));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;/*将变量添加到 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集合中的变量出现了重复*/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) {/*发现变量表为空 则创建一个变量表 默认有4个元素*/if (ngx_array_init(&cmcf->variables, cf->pool, 4,sizeof(ngx_http_variable_t))!= NGX_OK){return NGX_ERROR;}} else {/*变量表存在 则在变量表中进行查找*/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;}}/*发现变量表中没有这个变量 则将变量加入到变量表中*/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;//返回变量的索引值(即在变量数组中的序号)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) {/*使用的索引值超过了数组的范围 返回空值*/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];}/*获取配置的变量数组*/v = cmcf->variables.elts;if (ngx_http_variable_depth == 0) {/*如果变量的深度为0 表明变量的值正在进行刷新 返回空值*/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标记 则重新加上 (以防在get函数中被修改)*/r->variables[index].no_cacheable = 1;}/*返回变量*/return &r->variables[index];} /*获取变量出错 *///增加一次变量深度ngx_http_variable_depth++;/* valid设置为假 not_found设置为真 valid表明变量无效 not_found表示没找到变量的值 在下次调用中能复用还未刷新的变量值*/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标记 */if (!v->no_cacheable) {/*如果变量值可以缓存 返回变量值*/return v;}/*重置 valid和not_found标记 以通过get函数获取变量 即刷新变量的作用*/v->valid = 0;v->not_found = 0;}/*通过3中的函数来取得变量的值*/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);}/*发现变量的深度为0 注意变量深度是全局静态变量 针对所有请求而言意味着变量正在进行“刷新” 此时返回空值*/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函数计算得到变量的值*/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变量表的范围之内 则通过绑定的get函数取得变量值*/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结构中的偏移计算得到成员的地址*/s = (ngx_str_t *) ((char *) r + data);  if (s->data) { /*成员有数据 得到数据*/v->len = s->len;v->valid = 1;v->no_cacheable = 0;v->not_found = 0;v->data = s->data;} else {//成员中没有数据 进行not_found标记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;/*通过结构体的偏移得到 地址*/sp = (size_t *) ((char *) r + data);/*为变量值分配空间*/v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);if (v->data == NULL) {//分配失败 返回错误return NGX_ERROR;}/*拷贝数据到 变量值中*/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.通过变量值设置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)
{
...//得到变量的长度及数据信息    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;}/*取得位于结构体中的地址*/sp = (ssize_t *) ((char *) r + data);/* *引用取得值 并进行设置 内存地址无变化*/*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;/*通过结构体中的成员的偏移得到 hash表的元素*/h = *(ngx_table_elt_t **) ((char *) r + data); if (h) {/*存在 则取得元素的值 并设置到变量中*/v->len = h->value.len;v->valid = 1;v->no_cacheable = 0;v->not_found = 0;v->data = h->value.data;} else {/*不存在 进行not_found标记*/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;}/*内存池设置*/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数组*/if (ngx_array_init(&cmcf->prefix_variables, cf->pool, 8,sizeof(ngx_http_variable_t))!= NGX_OK){return NGX_ERROR;}/*添加http core变量 注意cv取得的是指针数组*/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;}/*设置变量值*/*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的变量数组*/v = cmcf->variables.elts;/*取得prefix_variables变量数组*/pv = cmcf->prefix_variables.elts;/*取得variables_keys数组*/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){/*设置变量的get函数 及回调参数*/v[i].get_handler = av->get_handler;v[i].data = av->data;/*将变量标记为 INDEXED*/av->flags |= NGX_HTTP_VAR_INDEXED;/*设置变量的flags标记*/v[i].flags = av->flags;//设置变量的索引值av->index = i;/*变量没有设置get函数或者变量为weak标记(即不通过get进行获取)跳出循环*/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) {/*变量存在 设置变量的get函数及回调参数以及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) {/*发现没有get函数 报错并且返回错误*/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进行索引查找的变量 将key值置为空值*/key[n].key.data = NULL;}}/*hash表进行初始化*/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数据拷贝到 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 
版权声明:本文为博主原创文章,转载请附上博文链接!

nginx处理http(http变量篇)相关推荐

  1. 【nginx分析之c语言篇】

    [nginx分析之c语言篇] 写在前面 struct中字段位宽 结构体中带方法名 写在前面 因为nginx的很多语法可能很多不常见,因此在这边做个记录或者简单的交流, struct中字段位宽 在ngi ...

  2. 自定义变量 配置文件_「系统架构」Nginx调优之变量的使用(3)

    在上一篇文章「系统架构」Nginx调优之变量的使用(2)中我们介绍了自定义变量和内置变量,下面我们继续接着介绍Nginx中变量的可见性和动态内置变量. 变量的可见性 nginx中的变量虽然不全是全局变 ...

  3. Nginx 内置绑定变量的介绍

    使用 Nginx 内置绑定变量 Nginx作为一个成熟.久经考验的负载均衡软件,与其提供丰富.完整的内置变量是分不开的,它极大增加了对Nginx网络行为的控制细度.这些变量大部分都是在请求进入时解析的 ...

  4. jq发送动态变量_「系统架构」Nginx调优之变量的使用(3)

    在上一篇文章「系统架构」Nginx调优之变量的使用(2)中我们介绍了自定义变量和内置变量,下面我们继续接着介绍Nginx中变量的可见性和动态内置变量. 变量的可见性 nginx中的变量虽然不全是全局变 ...

  5. 【python小课堂专栏】python小课堂11 - 变量篇

    python小课堂11 - 变量篇 前言 上周偷了点懒,周四到周末断更了,后来思考了下,前一阵儿的更新频率达到了日日更,虽然每章小知识都很详细..但是同学建议进度加快,emmm-然后我决定拉长更新周期 ...

  6. 入门学习Nginx代理服务器?就看这篇Nginx进阶学习最佳配置实践指南

    前置基础知识学习 1.Nginx基础安装与配置详细 https://blog.weiyigeek.top/2019/9-1-121.html 2.Nginx进阶学习之最佳配置实践指南 https:// ...

  7. nginx学习之静态内容篇(五)

    1.根目录和索引文件 server {root /www/data;location / {}location /images/ {}location ~ \.(mp3|mp4) {root /www ...

  8. Nginx 的内置变量

    在配置基于Nginx服务器的网站时,必然会使用到Nginx内置变量配置相关信息,下面将根据网上的相关资料进行整理,以方便在配置Nginx时查询. 内置变量存放在 ngx_http_core_modul ...

  9. nginx log_format 中的变量

    前言 nginx1.15 log_format 中的变量 $scheme :请求的协议,比如http.https: $host :请求的地址(IP或域名),比如127.0.0.1.localhost. ...

最新文章

  1. 重装windows2003遇到的老问题:0X0000007B和显卡驱动安装不上。
  2. VC 利用DLL共享区间在进程间共享数据及进程间广播消息
  3. PowerDesigner基本使用
  4. vs2012搭建gtest环境
  5. 【Java类加载机制】深入加载器
  6. Dirichlet Process和Hierarchical Dirichlet Process的理解(PPT)
  7. established 太多_ss -s closed过多,NON_ESTABLISHED告警
  8. CentOS7下使用yum快速安装配置oracle数据库
  9. 解决java.lang.NoClassDefFoundError: org/apache/log4j/Level
  10. 【个人作品】记之-串口日志记录工具
  11. android http统一回调,Android使用OKHttp构建带进度回调的多文件下载器
  12. 手把手教你用ppc手机远程控制电脑(摘自网络)
  13. ADC信噪比计算公式
  14. pyltp实现句法分析并画出句法图
  15. 43岁读NLP博士,一位70后的励志人生
  16. Python-文件操作
  17. html embed函数爬取,HTML DOM Embed用法及代码示例
  18. @ConditionalOnProperty
  19. 鸿蒙os基带版本,华为推出基于鸿蒙OS的Hi3861开发板
  20. pandas写入excel指定行_使用pandas操作excel

热门文章

  1. sas Data步数据读取流程详解
  2. android WebView 显示网页
  3. Wormholes--POJ 3259
  4. CodeForces - 1350E Orac and Game of Life(bfs)
  5. HDU - 4641 K-string(后缀自动机)
  6. HDU - 1528 Card Game Cheater(二分图最大匹配)
  7. HDU - 1847 Good Luck in CET-4 Everybody!(sg函数,水题)
  8. TensorFlow2-生成对抗网络
  9. Codeforces problem 67E(多边形求内核的应用)
  10. cocos2d-x游戏开发(六)自动释放池