ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

聊一聊 Nginx 变量(一)

2020-11-30 07:32:40  阅读:327  来源: 互联网

标签:http 变量 NGX variables Nginx 聊一聊 variable ngx


一、什么是变量?

变量可以认为是存放“值”的容器。而所谓“值”,在许多编程语言里,既可以是 3.14 这样的数值,也可以是 hello world 这样的字符串,甚至可以是像数组、哈希表这样的复杂数据结构。

Nginx 的变量和 perl、php 等语言的类似,由美元符号 $ 开头,随后跟着一个字符串,代表这个变量的名称,例如 $name,可选地,这个字符串可以用花括号包围,譬如 ${name} ,合法的变量名可用字符集为 [a-zA-Z0-9_]。特别地,Nginx 支持正则子组,即 $1,$2 这样的变量。变量值只有字符串这一种类型。

例子:

nginx.conf 文件中有以下配置:

server {
	listen 8080;

  location /test {
  		set $foo hello;
      echo "foo: $foo";
  }
}

使用 curl 这个 HTTP 客户端在命令行上请求这个 /test 接口,可以得到:

  $ curl 'http://localhost:8080/test'
    foo: hello

我们通过 set 配置指令对变量 $foo 进行了赋值操作, 把字符串 hello 赋给了它,通过“变量插值”的形式将其拼接到字符串中。

二、变量定义

1、主要数据结构

1)变量跟踪结构体

维护 Nginx 各模块支持的和配置文件中用到的变量信息结构体。

typedef struct {
    ...
    ngx_hash_t              variables_hash;
    ngx_array_t             variables;  /* array of ngx_http_variable_t */
    ..
    ngx_hash_keys_arrays_t  *variables_keys; /* 解析时的临时存储 */
    ...
} ngx_http_core_main_conf_t;

variables_keys 只是在解析时使用的临时存储,配置解析完成后,其中的变量信息会被 ngx_http_variables_init_vars 转存到 variablesvariables_hash 中。

不难知道变量拥有两种存放方式,第一种是储存在一个全局的 hash 表里(variables_hash);第二种则是储存在一个全局动态数组里(variables),每个变量存在一个对应的索引。

2)变量信息结构体

存储变量属性、变量 set_handlerget_handler 和这两个函数用到的参数值。

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;
};

变量的属性是以下几种属性的单例或组合:

NGX_HTTP_VAR_CHANGEABLE

变量可被覆盖

NGX_HTTP_VAR_NOCACHEABLE

不可缓存,对于 noncacheable 的变量,每次取值时都需要调用其 get_handler

NGX_HTTP_VAR_INDEXED

保存在动态数组中

NGX_HTTP_VAR_NOHASH

不保存在 hash 表中

NGX_HTTP_VAR_PREFIX

前缀型变量,如 arg_cookie_

示例:

static ngx_http_variable_t  ngx_http_fastcgi_vars[] = {

    { ngx_string("fastcgi_script_name"), NULL,
      ngx_http_fastcgi_script_name_variable, 0,
      NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },

    { ngx_string("fastcgi_path_info"), NULL,
      ngx_http_fastcgi_path_info_variable, 0,
      NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },

      ngx_http_null_variable
};
3)变量值结构体
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;
4)变量获取接口
/* 获取没有索引的变量 */
ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)

/* 根据索引获取变量,对于 nocaheable 变量会重新获取 */
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_indexed_variable(ngx_http_request_t *r, ngx_uint_t index);

2、变量分类

1)核心模块 ngx_http_core_module 提供的(内建)变量

使用 ngx_http_core_variables 描述, 由 preconfiguration 回调函数 ngx_http_variables_add_core_vars 进行定义:

ngx_int_t
ngx_http_variables_add_core_vars(ngx_conf_t *cf)
{
    ...
    ngx_http_core_main_conf_t *cmcf;

    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
    cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,
                                       sizeof(ngx_hash_keys_arrays_t));
    ...
    cmcf->variables_keys->pool = cf->pool;
    cmcf->variables_keys->temp_pool = cf->pool;
    ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL)

    for (v = ngx_http_core_variables; v->name.len; v++) {
        rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v,
                              NGX_HASH_READONLY_KEY);
        ...
    }
    ...
}
2)其他功能模块中添加的变量

ngx_http_fastcgi_module 提供的变量使用 ngx_http_fastcgi_vars 描述,由 preconfiguration 回调函数 ngx_http_fastcgi_add_variables 进行定义:

static ngx_int_t
ngx_http_fastcgi_add_variables(ngx_conf_t *cf)
{
    ngx_http_variable_t *var, *v;

    for (v = ngx_http_fastcgi_vars; v->name.len; v++) {
        var = ngx_http_add_variable(cf, &v->name, v->flags);
        ...
        var->get_handler = v->get_handler;
        var->data = v->data;
    }

    return NGX_OK;
}
3)使用 set 创建的变量

ngx_http_rewrite_module 提供的 set 指令定义的自定义变量由其配置解析函数 ngx_http_rewrite_set 进行定义:

static char *
ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ...
    value = cf->args->elts;
    ...
    value[1].len--;
    value[1].data++;

    v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE);
    ...
    index = ngx_http_get_variable_index(cf, &value[1]);
    ...
}

上述三种类型变量信息都被直接 (ngx_hash_add_key) 或间接 (ngx_http_add_variable) 存储到了 variables_keys 中。

标签:http,变量,NGX,variables,Nginx,聊一聊,variable,ngx
来源: https://www.cnblogs.com/fu3638/p/14059295.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有