agentzh 的 Nginx 教程 ---笔记

Nginx 变量名前面有一个 $ 符号,这是记法上的要求。所有的 Nginx 变量在 Nginx 配置文件中引用时都须带上$ 前缀。

标准 ngx_rewrite 模块的 set 配置指令对变量 $a 进行赋值操作:set $a "helloworld";

Nginx 的字符串记法支持使用花括号在 $ 之后把变量名围起来

Nginx 变量的创建和赋值操作发生在全然不同的时间阶段。Nginx 变量的创建只能发生在 Nginx配置加载的时候,或者说 Nginx启动的时候;而赋值操作则只会发生在请求实际处理的时候。这意味着不创建而直接使用变量会导致启动失败,同时也意味着我们无法在请求处理时动态地创建新的Nginx 变量。

Nginx 变量一旦创建,其变量名的可见范围就是整个 Nginx 配置,甚至可以跨越不同虚拟主机的 server配置块。

Nginx变量名的可见范围虽然是整个配置,但每个请求都有所有变量的独立副本,或者说都有各变量用来存放值的容器的独立副本,彼此互不干扰。

Nginx 变量的生命期是不可能跨越请求边界的。

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

Nginx 内建变量最常见的用途就是获取关于请求或响应的各种信息。例如由 ngx_http_core 模块提供的内建变量$uri,可以用来获取当前请求的 URI(经过解码,并且不含请求参数),而 $request_uri 则用来获取请求最原始的 URI(未经解码,并且包含请求参数)。

另一个特别常用的内建变量其实并不是单独一个变量,而是有无限多变种的一群变量,即名字以 arg_开头的所有变量,我们估且称之为 $arg_XXX 变量群。一个例子是 $arg_name,这个变量的值是当前请求名为 name 的URI 参数的值,而且还是未解码的原始形式的值。

Nginx 会在匹配参数名之前,自动把原始请求中的参数名调整为全部小写的形式。

如果你想对 URI 参数值中的 %XX 这样的编码序列进行解码,可以使用第三方 ngx_set_misc 模块提供的set__uri 配置指令:
location /test {
        set__uri $name $arg_name;
        set__uri $class $arg_class;

        echo "name: $name";
        echo "class: $class";
    }
类似 $arg_XXX 的内建变量还有不少,比如用来取 cookie 值的 $cookie_XXX 变量群,用来取请求头的$http_XXX 变量群,以及用来取响应头的 $sent_http_XXX 变量群。

需要指出的是,许多内建变量都是只读的,比如我们刚才介绍的 $uri 和 $request_uri.对只读变量进行赋值是应当绝对避免的,因为会有意想不到的后果

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

对 $args 的修改会影响到所有部分的功能。

修改 $args 变量会影响标准的 HTTP 代理模块 ngx_proxy

Nginx 模块可以为其创建的变量选择使用值容器,作为其“取处理程序”计算结果的缓存。显然, ngx_map模块认为变量间的映射计算足够昂贵,需要自动将因变量的计算结果缓存下来,这样在当前请求的处理过程中如果再次读取这个因变量,Nginx就可以直接返回缓存住的结果,而不再调用该变量的“取处理程序”再行计算了。

$arg_XXX 并不会使用值容器进行缓存,类似 ngx_map 模块,标准的 ngx_geo等模块也一样使用了变量值的缓存机制。

map 指令只能在 http 块中使用

这种只在实际使用对象时才计算对象值的技术,在计算领域被称为“惰性求值”(lazy evaluation)

“主动求值”语义其实在 Nginx 里面更为常见:set $b "$a,$a";
这里会在执行 set 规定的赋值操作时,“主动”地计算出变量 $b 的值,而不会将该求值计算延缓到变量 $b实际被读取的时候。

在 Nginx 世界里有两种类型的“请求”,一种叫做“主请求”(mainrequest),而另一种则叫做“子请求”(subrequest)

所谓“主请求”,就是由 HTTP 客户端从 Nginx 外部发起的请求。包括 echo_exec 和 rewrite指令发起“内部跳转”

而“子请求”则是由 Nginx 正在处理的请求在 Nginx 内部发起的一种级联请求。“子请求”在外观上很像 HTTP请求,但实现上却和 HTTP 协议乃至网络通信一点儿关系都没有。它是 Nginx内部的一种抽象调用,目的是为了方便用户把“主请求”的任务分解为多个较小粒度的“内部请求”,并发或串行地访问多个 location接口,然后由这些 location接口通力协作,共同完成整个“主请求”。当然,“子请求”的概念是相对的,任何一个“子请求”也可以再发起更多的“子子请求”,甚至可以玩递归调用(即自己调用自己)。当一个请求发起一个“子请求”的时候,按照Nginx 的术语,习惯把前者称为后者的“父请求”(parent request)。
eg. 第三方 ngx_echo 模块的 echo_location 
“子请求”方式的通信是在同一个虚拟主机内部进行的,所以 Nginx 核心在实现“子请求”的时候,就只调用了若干个 C函数,完全不涉及任何网络或者 UNIX 套接字(socket)通信。我们由此可以看出“子请求”的执行效率是极高的。
不幸的是,一些 Nginx模块发起的“子请求”却会自动共享其“父请求”的变量值容器,比如第三方模块ngx_auth_request模块发起的“子请求”确实是与其“父请求”共享一套 Nginx 变量的值容器。

并非所有的内建变量都作用于当前请求。少数内建变量只作用于“主请求”,比如由标准模块 ngx_http_core提供的内建变量 $request_method.
变量 $request_method 在读取时,总是会得到“主请求”的请求方法,比如 GET、POST 之类。
不能通过标准的 $request_method 变量取得“子请求”的请求方法。为了达到目的,我们需要求助于第三方模块ngx_echo 提供的内建变量 $echo_request_method

没有值的变量也有两种特殊的值:一种是“不合法”(invalid),另一种是“没找到”(not found)

$arg_XXX 变量在请求 URL 中有多个同名 XXX 参数时,就只会返回最先出现的那个 XXX参数的值,而默默忽略掉其他实例
 
http://agentzh.org/misc/nginx/agentzh-nginx-tutorials-zhcn.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值