概述
详细原文查看这里:http://blog.sina.com.cn/s/blog_6d579ff40100wk2j.html
另一篇归纳原文的文章看这里:http://blog.csdn.net/yankai0219/article/details/8070790
变量插值:
所有的 Nginx变量在 Nginx配置文件中引用时都须带上 $前缀,用$符号+变量名来构造新的变量,这种方式叫做变量插值。
例如:
location test{
set $a hello;
set $b "$a ,world";
echo "b: $b";
}
访问: curl http://localhost/test/
输出:b: hello world
说明:上述set是HttpRewriteModule的指令,而echo是HttpEchoModule指令。可见这两个模块都支持变量插值。
但是并不是所有模块都支持变量插值,事实上,指令参数是否允许“变量插值”,取决于该指令的实现模块。
变量使用注意点:
当变量后面直接接其他字符串时,需要用{}将变量名括起来,否则会将变量名和后面的字符串连在一起当成一个变量名
例如:
location /test {
set $variable "hello";
echo"${variable}world";
}
变量必须先创建再使用,否则报错
例如:
server {
listen 80;
location /test
{
echo $foo;
}
}
访问: curl http://localhost/test/
报错:[emerg] unknown"foo" variable
说明:nginxnginx变量的创建和赋值操作发生在全然不同的时间阶段。Nginx变量的创建只能发生在 Nginx配置加载的时候,或者说 Nginx启动的时候;而赋值操作则只会发生在请求实际处理的时候。这意味着不创建而直接使用变量会导致启动失败,同时也意味着我们无法在请求处理时动态地创建新的 Nginx变量
变量的可见性和作用域:
Nginx 变量一旦创建,其变量名的可见范围就是整个 Nginx 配置,甚至可以跨越不同虚拟主机的 server 配置块。例如:
server {
listen 80;
location /foo {
echo "foo =[$foo]";
}
location /bar {
set $foo 32;
echo "foo =[$foo]";
}
}
说明:这里我们在 location /bar 中用 set 指令创建了变量 $foo ,于是在整个配置文件中这个变量都是可见的,因此我们可以在 location /foo 中直接引用这个变量而不用担心 Nginx 会报错。
访问这两个接口的结果:
$ curl 'http://localhost/foo'
foo = []
$ curl 'http://localhost/bar'
foo = [32]
$ curl 'http://localhost/foo'
foo = []
从本例子得出另一个变量特性:
Nginx 变量名的可见范围虽然是整个配置,但每个请求都有所有变量的独立副本,或者说都有各变量用来存放值的容器的独立副本,彼此互不干扰。
比如前面我们请求了 /bar接口后,$foo变量被赋予了值 32,但它丝毫不会影响后续对 /foo接口的请求所对应的 $foo值(它仍然是空的!),因为各个请求都有自己独立的 $foo变量的副本
对于 Nginx新手来说,最常见的错误之一,就是将 Nginx变量理解成某种在请求之间全局共享的东西,或者说“全局变量”。而事实上,Nginx变量的生命期是不可能跨越请求边界的
另外一个误区是:认为变量容器的生命期,是与 l
ocation
配置块绑定的。其实不然。我们来看一个涉及“内部跳转”的例子
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 这样的“外部跳转”。
内建变量
常见的内建变量:$uri: 用来获取当前请求的URI(经过解码,并且不包含请求参数)
$request_uri:用来获取请求最原始的URI(未经解码,并且包含请求参数)
location /test {
echo "uri = $uri";
echo "request_uri =$request_uri";
}
请求和响应:
$ 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_xxx变量群:用来获取当前请求名为xxx的URI参数的值
location /test {
echo "name:$arg_name";
echo "class:$arg_class";
}
请求和响应:
$ 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,等等,Nginx会在匹配参数名之前,自动把原始请求中的参数名调整为全部小写的形式:
$ curl 'http://localhost:8080/test?NAME=Marry'
name: Marry
class:
$ curl 'http://localhost:8080/test?Name=Jimmy'
name: Jimmy
class:
$cookie_xxx变量群:用来获取cookie值
$http_xxx变量群:用来获取请求头的值
$send_http_xxx变量群:用来获取响应头的值
$args:返回当前请求的URL参数串(即请求URL中问号后面的部分)
如果你尝试改写另外一些只读的内建变量,比如 $arg_XXX 变量,在某些 Nginx 的版本中甚至可能导致进程崩溃。
location /bad {
set $uri /blah;
echo $uri;
}
这个有问题的配置会让 Nginx 在启动的时候报出一条令人匪夷所思的错误:
[emerg] the duplicate "uri" variable in ...
也有一些内建变量是支持改写的,其中一个例子是 $args. 这个变量在读取时返回当前请求的 URL 参数串(即请求 URL 中问号后面的部分,如果有的话 ),而在赋值时可以直接修改参数串
例如:
location /test {
set $orig_args $args;
set $args "a=3&b=4";
echo "original args: $orig_args";
echo "args: $args";
}
访问和输出:
$ curl 'http://localhost:8080/test'
original args:
args: a=3&b=4
$ curl 'http://localhost:8080/test?a=0&b=1&c=2'
original args: a=0&b=1&c=2
args: a=3&b=4
像 $arg_XXX 这样具有无数变种的变量群,是“未索引的”。当读取这样的变量时,其实是它的“取处理程序”(get(xxx))在起作用,即实时扫描当前请求的 URL 参数串,提取出变量名所指定的 URL 参数的值。很多新手都会对 $arg_XXX的实现方式产生误解,以为 Nginx 会事先解析好当前请求的所有 URL 参数,并且把相关的$arg_XXX变量的值都事先设置好。然而事实并非如此,Nginx 根本不会事先就解析好 URL 参数串,而是在用户读取某个$arg_XXX 变量时,调用其“取处理程序”,即时去扫描 URL 参数串。类似地,内建变量 $cookie_XXX 也是通过它的“取处理程序”,即时去扫描
Cookie
请求头中的相关定义的。
最后
以上就是等待鱼为你收集整理的nginx 变量_1变量插值:变量使用注意点:变量的可见性和作用域:内建变量的全部内容,希望文章能够帮你解决nginx 变量_1变量插值:变量使用注意点:变量的可见性和作用域:内建变量所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复