• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2020-10-26 01:54 Aet 隐藏边栏 |   抢沙发  11 
文章评分 1 次,平均分 5.0

变量

只能存放字符串

用户变量

通过set指令创建的nginx变量

通过不支持“变量插值”的模块配置指令专门构造出取值为\$的 Nginx 变量,然后再在echo中使用这个变量

nginx变量一旦创建,变量名的可见范围就是整个nginx配置。但是,当操作的时候,其实操作的是自个持有的副本内容。

nginx变量容器的生命期是与当前正在处理的请求绑定的,而与location无关。

内建变量

ngx_http_core模块

  • \$uri
    • 用来获取当前请求的URI(经过解码,并且不包含请求参数)
  • \$request_uri
    • 用来获取最原始的URI(未经过解码,并且包含请求参数)

\$arg_xxx

  • \$arg_name
    • 当前请求名为 name 的 URI 参数的值,而且还是未解码的原始形式的值
    • 不仅可以匹配 name 参数,也可以匹配 NAME 参数,抑或是 Name,等等

ngx_set_misc模块

  • set_unescape_uri
    • 对 URI 参数值中的 %XX 这样的编码序列进行解码

应避免对这种内建变量进行赋值。

可变值内建变量

也有一些内建变量是支持改写的,如\$args,这个变量在读取时返回当前请求的 URL 参数串(即请求 URL 中问号后面的部分,如果有的话),而在赋值时可以直接修改参数串。

这里在 http 配置块中定义了两个虚拟主机。第一个虚拟主机监听 8080 端口,其 /test 接口自己通过改写 $args 变量,将当前请求的 URL 参数串无条件地修改为 foo=1&bar=2. 然后 /test 接口再通过 ngx_proxy 模块的 proxy_pass 指令配置了一个反向代理,指向本机的 8081 端口上的 HTTP 服务 /args. 默认情况下, ngx_proxy 模块在转发 HTTP 请求到远方 HTTP 服务的时候,会自动把当前请求的 URL 参数串也转发到远方。

而本机的 8081 端口上的 HTTP 服务正是由我们定义的第二个虚拟主机来提供的。我们在第二个虚拟主机的 location /args 中利用 echo 指令输出当前请求的 URL 参数串,以检查 /test 接口通过 ngx_proxy 模块实际转发过来的 URL 请求参数串。

变量映射

在设置了“取处理程序”的情况下,Nginx 变量也可以选择将其值容器用作缓存,这样在多次读取变量的时候,就只需要调用“取处理程序”计算一次。

这里用到了标准 ngx_map 模块的 map 配置指令,我们有必要在此介绍一下。map 在英文中除了“地图”之外,也有“映射”的意思。比方说,中学数学里讲的“函数”就是一种“映射”。而 Nginx 的这个 map 指令就可以用于定义两个 Nginx 变量之间的映射关系,或者说是函数关系。回到上面这个例子,我们用 map 指令定义了用户变量 \$foo 与 $args 内建变量之间的映射关系。特别地,用数学上的函数记法 y = f(x) 来说,我们的 \$args 就是“自变量” x,而 \$foo 则是“因变量” y,即 \$foo的值是由 $args 的值来决定的,或者按照书写顺序可以说,我们将 $args 变量的值映射到了 \$foo 变量上。

第一行的 default 是一个特殊的匹配条件,即当其他条件都不匹配的时候,这个条件才匹配。当这个默认条件匹配时,就把“因变量” \$foo 映射到值 0

花括号中第二行的意思是说,如果“自变量” \$args 精确匹配了 debug 这个字符串,则把“因变量” \$foo 映射到值 1. 将这两行合起来,我们就得到如下完整的映射规则:当 $args 的值等于 debug 的时候,\$foo 变量的值就是 1,否则 \$foo 的值就为 0

明白了 map 指令的含义,再来看 location /test. 在那里,我们先把当前 \$foo 变量的值保存在另一个用户变量 \$orig_foo 中,然后再强行把 $args 的值改写为 debug,最后我们再用 echo 指令分别输出 \$orig_foo 和 \$foo 的值。

从逻辑上看,似乎当我们强行改写 $args 的值为 debug 之后,根据先前的 map 映射规则,\$foo 变量此时的值应当自动调整为字符串 1, 而不论 \$foo 原先的值是怎样的。然而测试结果并非如此:

第一行输出指示 \$orig_foo 的值为 0,这正是我们期望的:上面这个请求并没有提供 URL 参数串,于是 $args 最初的取值就是空,再根据我们先前定义的映射规则,\$foo 变量在第一次被读取时的值就应当是 0(即匹配默认的那个 default 条件)。

而第二行输出显示,在强行改写 $args 变量的值为字符串 debug 之后,\$foo 的条件仍然是 0 ,这显然不符合映射规则,因为当 $argsdebug 时,\$foo 的值应当是 1. 这究竟是为什么呢?

其实原因很简单,那就是 \$foo 变量在第一次读取时,根据映射规则计算出的值被缓存住了。刚才我们说过,Nginx 模块可以为其创建的变量选择使用值容器,作为其“取处理程序”计算结果的缓存。显然, ngx_map 模块认为变量间的映射计算足够昂贵,需要自动将因变量的计算结果缓存下来,这样在当前请求的处理过程中如果再次读取这个因变量,Nginx 就可以直接返回缓存住的结果,而不再调用该变量的“取处理程序”再行计算了。

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2021-11-20
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享