server {
listen 8080;
location /test {
set $foo hello;
echo "foo: $foo";
}
}
2、输出$
geo $dollar {
default "$";
}
server {
listen 8080;
location /test {
echo "This is a dollar sign: $dollar
}
}
结果
$ curl 'http://localhost:8080/test'
This is a dollar sign: $
3、区分空格
server {
listen 8080;
location /test {
set $first "hello ";
echo "${first}world";
}
}
结果:
$ curl 'http://localhost:8080/test
hello world
4、变量上下文
Nginx 变量名的可见范围虽然是整个配置,但每个请求都有所有变量的独立副本,或者说都有各变量用来存放值的容器的独立副本,彼此互不干扰
5、内部跳转
server {
listen 8080;
location /foo {
set $a hello;
echo_exec /bar; //通rewrite ^/bar
}
location /bar {
echo "a = [$a]";
}
}
echo_exec 配置指令,发起到
location /bar 的“内部跳转”。
Nginx变量值容器的生命期是与当前正在处理的请求绑定的,而与 location无关
6、nginx内建变量
Nginx 内建变量最常见的用途就是获取关于请求或响应的各种信息
location /test {
echo "uri = $uri";
echo "request_uri = $request_uri
}
运行结果
$ curl 'http://localhost:8080/test?a=3&b=4'
uri = /test
request_uri = /test?a=3&b=4
7、$arg_XXX
另一个特别常用的内建变量其实并不是单独一个变量,而是有无限多变种的一群变量,即名字以 arg_开头的所有变量,我们估且称之为$arg_XXX 变量群。一个例子是$arg_name,这个变量的值是当前请求名为 name 的 URI 参数的值,而且还是未解码的原始形式的值
location /test {
echo "name: $arg_name";
echo "class: $arg_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
Nginx 会在匹配参数名之前,自动把原始请求中的参数名调整为全部小写的形式
8、对 URI 参数值中的 %XX 这样的编码序列进行解码
set_unescape_uri $name
9、比如用来取 cookie 值的$cookie_XXX 变量群,用来取请求头的 $http_XXX 变量群,以及用来取响应头的 $sent_http_XXX 变量群。可以参考 ngx_http_core 模块的官方文档
10、修改 $args 变量影响标准的 HTTP 代理模块 ngx_proxy 的例子
server {
listen 8080;
location /test {
set $args "foo=1&bar=2";
proxy_pass http://127.0.0.1:8081/args;
}
}
server {
listen 8081;
location /args {
echo "args: $args";
}
}
运行结果
$ curl 'http://localhost:8080/test?blah=7'
args: foo=1&bar=2
11、ngx_map
map $args $foo {
default 0;
debug 1;
}
server {
listen 8080;
location /test {
set $orig_foo $foo;
set $args debug;
echo "orginal foo: $orig_foo";
echo "foo: $foo";
}
}
当 $args 的值等于 debug 的时候,$foo 变量的值就是 1,否则 $foo 的值就为 0.
ngx_map 模块认为变量间的映射计算足够昂贵,需要自动将因变量的计算结果缓存下来,这样在当前请求的处理过程中如果次读取这个因变量,Nginx 就可以直接返回缓存住的结果,而不再调用该变量的“取处理程序”再行计算了。
$ curl 'http://localhost:8080/test'
original foo: 0
foo: 0
$ curl 'http://localhost:8080/test?debug'
original foo: 1
foo: 1
在上面的例子中,我们还应当注意到 map 指令是在 server 配置块之外,也就是在最外围的 http 配置块中定义的。很多读者可能会对此感到奇怪,毕竟我们只是在location /test 中用到了它。这倒不是因为我们不想把 map 语句直接挪到location 配置块中,而是因为 map 指令只能在 http 块中使用!
12、子请求
location /main {
echo_location /foo;
echo_location /bar;
}
location /foo {
echo foo;
}
location /bar {
echo bar;
}
“子请求”方式的通信是在同一个虚拟主机内部进行的,所以 Nginx 核心在实现“子请求”的时候,就只调用了若干个 C 函数,完全不涉及任何网络或者 UNIX 套接字(socket)通信
13、子请求变量
location /main {
echo "main args: $args";
echo_location /sub "a=1&b=2";
}
location /sub {
echo "sub args: $args";
}
运行结果:
$ curl 'http://localhost:8080/main?c=3'
main args: c=3
sub args: a=1&b=2
但不幸的是,并非所有的内建变量都作用于当前请求。少数内建变量只作用于“主请求”,比如由标准模块 ngx_http_core 提供的内建变量$request_method.变量 $request_method。
变量 $request_method 在读取时,总是会得到“主请求”的请求方法,比如 GET、POST 之类。
为了达到我们最初的目的,我们需要求助于第三方模块 ngx_echo 提供的内建变量 $echo_request_method:
location /main {
echo "main method: $echo_request_method";
echo_location /sub;
}
location /sub {
echo "sub method: $echo_request_method";
}
此时的输出终于是我们想要的了:
$ curl --data hello 'http://localhost:8080/main'
main method: POST
sub method: GET
14、变量找不到和空字符串
ngx_lua,我们可以轻松地在 Lua 代码中做到这一点
location /test {
content_by_lua '
if ngx.var.arg_name == nil then
ngx.say("name: missing")
else
ngx.say("name: [", ngx.var.arg_name, "]")
end
';
}
15、我们可以选择在 Nginx不同的请求处理阶段插入我们的Lua 代码。这些 Lua 代码既可以直接内联在 Nginx 配置文件中,也可以单独放置在外部 .lua 文件里,然后在 Nginx 配置文件中引用 .lua文件的路径。
16、ngx.var
回到上面这个例子,我们在 Lua 代码里引用 Nginx 变量都是通过ngx.var 这个由 ngx_lua 模块提供的Lua 接口。比如引用 Nginx 变量$VARIABLE 时,就在 Lua 代码里写作 ngx.var.VARIABLE 就可以了。当 Nginx 变量 $arg_name 为特殊值“没找到”(或者“不合法”)时,ngx.var.arg_name 在 Lua 世界中的值就是 nil,即 Lua 语言里的“空”(不同于 Lua 空字符串)。我们在 Lua 里输出响应体内容的时候,则使用了 ngx.say 这个 Lua 函数,也是 ngx_lua 模块提供的,功能上等价于 ngx_echo 模块的 echo配置指令。
17、nil值
在 Lua 里访问未创建的 Nginx 用户变量时,在 Lua 里也会得到 nil 值,而不会像先前的例子那样直接让 Nginx 拒绝加载配置:
location /test {
content_by_lua '
ngx.say("$blah = ", ngx.var.blah)
';
} curl 'http://localhost:8080/test'
$blah = nil