`
风过无声
  • 浏览: 92097 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Nginx 变量漫谈(二)生命周期&内置变量 (转载)

 
阅读更多

转载自 http://blog.sina.com.cn/openresty

 

关于 Nginx 变量的另一个常见误区是认为变量容器的生命期,是与 location 配置块绑定的。其实不然。我们来看一个涉及“内部跳转”的例子:

    server {

        listen 8080;

 

        location /foo {

            set $a hello;

            echo_exec /bar;

        }

 

        location /bar {

            echo "a = [$a]";

        }

    }

这里我们在 location /foo 中,使用第三方模块 ngx_echo 提供的 echo_exec 配置指令,发起到 location /bar 的“内部跳转”。所谓“内部跳转”,就是在处理请求的过程中,于服务器内部,从一个 location 跳转到另一个 location 的过程。这不同于利用 HTTP 状态码 301 和 302 所进行的“外部跳转”,因为后者是由 HTTP 客户端配合进行跳转的,而且在客户端,用户可以通过浏览器地址栏这样的界面,看到请求的 URL 地址发生了变化。内部跳转和 Bourne Shell(或 Bash)中的 exec 命令很像,都是“有去无回”。另一个相近的例子是 C 语言中的 goto 语句。

 

    既然是内部跳转,当前正在处理的请求就还是原来那个,只是当前的 location 发生了变化,所以还是原来的那一套 Nginx 变量的容器副本。对应到上例,如果我们请求的是 /foo 这个接口,那么整个工作流程是这样的:先在 location /foo 中通过 set 指令将 $a 变量的值赋为字符串 hello,然后通过 echo_exec 指令发起内部跳转,又进入到 location /bar 中,再输出 $a 变量的值。因为 $a 还是原来的 $a,所以我们可以期望得到 hello 这行输出。测试证实了这一点:

    $ curl localhost:8080/foo

    a = [hello]

但如果我们从客户端直接访问 /bar 接口,就会得到空的 $a 变量的值,因为它依赖于 location /foo 来对 $a 进行初始化。

 

    从上面这个例子我们看到,一个请求在其处理过程中,即使经历多个不同的 location 配置块,它使用的还是同一套 Nginx 变量的副本。这里,我们也首次涉及到了“内部跳转”这个概念。值得一提的是,标准 ngx_rewrite 模块的 rewrite 配置指令其实也可以发起“内部跳转”,例如上面那个例子用 rewrite 配置指令可以改写成下面这样的形式:

    server {

        listen 8080;

 

        location /foo {

            set $a hello;

            rewrite ^ /bar;

        }

 

        location /bar {

            echo "a = [$a]";

        }

    }

其效果和使用 echo_exec 是完全相同的。后面我们还会专门介绍这个 rewrite 指令的更多用法,比如发起 301 和 302 这样的“外部跳转”。

 

    从上面这个例子我们看到,Nginx 变量值容器的生命期是与当前正在处理的请求绑定的,而与 location 无关。

 

    前面我们接触到的都是通过 set 指令隐式创建的 Nginx 变量。这些变量我们一般称为“用户自定义变量”,或者更简单一些,“用户变量”。既然有“用户自定义变量”,自然也就有由 Nginx 核心和各个 Nginx 模块提供的“预定义变量”,或者说“内建变量”(builtin variables)。

 

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

    location /test {

        echo "uri = $uri";

        echo "request_uri = $request_uri";

    }

这里为了简单起见,连 server 配置块也省略了,和前面所有示例一样,我们监听的依然是 8080 端口。在这个例子里,我们把 $uri 和 $request_uri 的值输出到响应体中去。下面我们用不同的请求来测试一下这个 /test 接口:

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

    uri = /test

    request_uri = /test

 

    $ curl 'http://localhost:8080/test?a=3&b=4'

    uri = /test

    request_uri = /test?a=3&b=4

 

    $ curl 'http://localhost:8080/test/hello%20world?a=3&b=4'

    uri = /test/hello world

    request_uri = /test/hello%20world?a=3&b=4

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

    location /test {

        echo "name: $arg_name";

        echo "class: $arg_class";

    }

然后在命令行上使用各种参数组合去请求这个 /test 接口:

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

    name: 

    class: 

 

    $ curl 'http://localhost:8080/test?name=Tom&class=3'

    name: Tom

    class: 3

 

    $ curl 'http://localhost:8080/test?name=hello%20world&class=9'

    name: hello%20world

    class: 9

其实 $arg_name 不仅可以匹配 name 参数,也可以匹配 NAME 参数,抑或是 Name,等等:

    $ curl 'http://localhost:8080/test?NAME=Marry'

    name: Marry

    class: 

 

    $ curl 'http://localhost:8080/test?Name=Jimmy'

    name: Jimmy

    class:

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

 

    如果你想对 URI 参数值中的 %XX 这样的编码序列进行解码,可以使用第三方 ngx_set_misc 模块提供的 set_unescape_uri 配置指令:

    location /test {

        set_unescape_uri $name $arg_name;

        set_unescape_uri $class $arg_class;

 

        echo "name: $name";

        echo "class: $class";

    }

现在我们再看一下效果:

    $ curl 'http://localhost:8080/test?name=hello%20world&class=9'

    name: hello world

    class: 9

空格果然被解码出来了!

 

    从这个例子我们同时可以看到,这个 set_unescape_uri 指令也像 set 指令那样,拥有自动创建 Nginx 变量的功能。后面我们还会专门介绍到 ngx_set_misc 模块。

    像 $arg_XXX 这种类型的变量拥有无穷无尽种可能的名字,所以它们并不对应任何存放值的容器。而且这种变量在 Nginx 核心中是经过特别处理的,第三方 Nginx 模块是不能提供这样充满魔法的内建变量的。

 

    类似 $arg_XXX 的内建变量还有不少,比如用来取 cookie 值的 $cookie_XXX 变量群,用来取请求头的 $http_XXX 变量群,以及用来取响应头的 $sent_http_XXX 变量群。这里就不一一介绍了,感兴趣的读者可以参考 ngx_http_core 模块的官方文档。

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

    ? location /bad {

    ?     set $uri /blah;

    ?     echo $uri;

    ? }

这个有问题的配置会让 Nginx 在启动的时候报出一条令人匪夷所思的错误:

    [emerg] the duplicate "uri" variable in ...

如果你尝试改写另外一些只读的内建变量,比如 $arg_XXX 变量,在某些 Nginx 的版本中甚至可能导致进程崩溃。

分享到:
评论

相关推荐

    nginx内置变量

    **Nginx内置变量概述** Nginx是一个高性能的HTTP和反向代理服务器,它具有模块化设计和出色的并发处理能力。在Nginx配置中,内置变量扮演着至关重要的角色,它们允许管理员动态地获取关于请求、客户端、服务器状态...

    Nginx内置变量列表

    nginx内置变量列表,根据 Nginx 源码文件 ngx_http_variables.c 提取了nginx 的内置变量。

    nginx自定义变量与内置预定义变量的使用

    这些内置变量极大地扩展了Nginx配置的灵活性,允许开发者根据HTTP请求的具体情况做出相应的响应。 综上所述,Nginx的自定义变量和内置预定义变量提供了强大的配置能力,使Nginx成为了一个高度可定制的Web服务器和...

    nginx 内置变量详解及隔离进行简单的拦截

    1,nginx内置变量 nginx 有很多内置变量可以进行简单的过滤。 $arg_name 请求行中的name参数。 $args 请求行中参数字符串。 $cookie_name 名为name的cookie。 与$uri相同。 $http_name 任意请求头的值;变量名的后...

    Nginx 内置预变量都有哪些?

    Nginx 内置预变量都有哪些?

    NGINX conf 配置文件中的变量大全

    在深入探讨NGINX配置文件中的变量之前,我们先简要了解一下NGINX。NGINX是一款高性能的HTTP和反向代理服务器,广泛应用于互联网上处理高并发连接、静态文件服务以及负载均衡等场景。其配置文件是实现NGINX功能的核心...

    nginx 内置变量表 Excel版.rar

    经常需要配置Nginx ,其中有许多以 $ 开头的变量,经常需要查阅nginx 所支持的变量。 可能是对 Ngixn资源不熟悉,干脆就直接读源码,分析出支持的变量。 Nginx支持的http变量实现在 ngx_http_variables.c 的 ngx_...

    agentzh 的 Nginx 教程(版本 2016.07.21)整理成pdf 添加书签

    - **内置变量与自定义变量**:比较内置变量与用户自定义变量的区别。 - **变量与HTTP请求处理**:探讨变量如何参与HTTP请求的处理流程。 - **变量与安全性**:分析变量使用不当可能带来的安全风险。 #### Nginx ...

    nginx/1.21.6 &nginx-http-flv-module-1.2.10

    标题 "nginx/1.21.6 & nginx-...用户可以使用这个二进制文件快速部署一个支持流媒体的Nginx服务器,无需从源码编译。通过适当的配置,该服务器可以处理HTTP FLV流,接受RTMP推送,同时保证数据传输的安全性。

    Nginx知识体系入门实践.zip

    01.Nginx快速入门 02.Nginx常用模块 03.Nginx提供静态资源WEB服务 04.Nginx提供代理服务 05.Nginx提供负载均衡 06.Nginx提供ProxyCache缓存服务 07.Nginx Rewrite跳转规则与实践 08.Nginx构建Https加密传输网站(基于...

    nginx全局变量整理小结

    Nginx 全局变量整理小结 Nginx 全局变量是 Nginx 服务器中的一组预定义变量,用于存储当前请求的信息和服务器的状态。这些变量可以在 Nginx 配置文件中使用,帮助管理员更好地管理和优化服务器。这篇文章将对 Nginx...

    nginx+keepalive主从 双机热备 + 自动切换解决方案

    ### Nginx+Keepalive 主从双机热备与自动切换解决方案 在现代网络环境中,为了提高服务的稳定性和可用性,通常会采用负载均衡技术和高可用性集群方案。本篇将详细介绍如何通过Nginx 和 Keepalive 实现主从双机热备...

    Nginx教程.pdf

    5. **变量与函数**:某些Nginx模块还提供了内置函数来处理变量,例如`map`指令可以用来转换变量值。 #### 二、Nginx配置指令的执行顺序 1. **配置结构**:Nginx的配置文件是由一系列嵌套的块构成的,每个块可以...

    分享最新版 nginx内置变量 大全

    nginx内置变量 内置变量存放在 ngx_http_core_module 模块中,变量的命名方式和apache 服务器变量是一致的。总而言之,这些变量代表着客户端请求头的内容,例如$http_user_agent, $http_cookie, 等等。下面是nginx...

    agentzh写的Nginx教程

    12. Nginx变量系列:该系列包含了至少八篇专注于Nginx变量的文章,Nginx变量是Nginx配置中非常重要的一个方面,变量可以用于配置文件中的各种指令里,以实现更灵活的配置。 13. Nginx指令执行顺序系列:该系列文章...

    Nginx-ngx_lua模块原理和内置函数.docx

    - 每个 Nginx worker 进程都会创建一个 Lua 虚拟机 (LuaVM),该 VM 在整个 worker 的生命周期内都是共享的。 - 这种设计可以减少每次请求时创建和销毁虚拟机的开销,提高性能。 2. **Nginx I/O 原语封装:** - ...

Global site tag (gtag.js) - Google Analytics