浅析Nginx配置文件中的变量的编写使用

2019-10-17 19:51:37王振洲

 
然后在命令行上使用各种参数组合去请求这个 /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 的版本中甚至可能导致进程崩溃。
也有一些内建变量是支持改写的,其中一个例子是 $args. 这个变量在读取时返回当前请求的 URL 参数串(即请求 URL 中问号后面的部分,如果有的话 ),而在赋值时可以直接修改参数串。我们来看一个例子:

location /test {  
  set $orig_args $args;  
  set $args "a=3&b=4";  
  echo "original args: $orig_args";  
  echo "args: $args";  
}