Nginx 变量漫谈(二)
(2011-12-02 22:07:11)| 标签: 杂谈 | 分类: Nginx变量 | 
 location
配置块绑定的。其实不然。我们来看一个涉及“内部跳转”的例子:
这里我们在 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 配置指令可以改写成下面这样的形式:
其效果和使用 echo_exec 是完全相同的。后面我们还会专门介绍这个 rewrite 指令的更多用法,比如发起 301 和
302 这样的“外部跳转”。
 location 无关。
 
 
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 会在匹配参数名之前,自动把原始请求中的参数名调整为全部小写的形式。
 %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 
空格果然被解码出来了!
 
 
 
 
这个有问题的配置会让 Nginx 在启动的时候报出一条令人匪夷所思的错误:
[emerg] the duplicate "uri" variable in ... 
如果你尝试改写另外一些只读的内建变量,比如 $arg_XXX 变量,在某些 Nginx 的版本中甚至可能导致进程崩溃。
 

 加载中…
加载中…