以下学习参考agentzh(章亦春)的nginx教程以及google老师
–
location /hi{
set $a "hi";
return 200 "hello";
}
hi
,注意的是,nignx启动时,变量已创建,但是在具体运行到这里后变量值才被赋值,也就是说,创建和赋值是分开的。–
nginx有很多内建的变量群,需要注意,在 $arg_xxx
中,可以获取名为xxx的请求参数,并且自动将所有get的参数转为小写之后进行匹配。
location /hi{
add_header oriuri $uri;
add_header requri $request_uri;
add_header post $arg_post;
return 301 "www.baidu.com";
}
curl hongjian.cn/hi?post=helloworld -v
< HTTP/1.1 301 Moved Permanently
< Server: nginx
< Date: Sun, 23 Apr 2017 10:10:12 GMT
< Content-Type: text/html
< Content-Length: 178
< Connection: keep-alive
< Location: www.baidu.com
< oriuri: /hi
< requri: /hi?post=helloworld
< post: helloworld
类似 argXXX的内建变量还有不少,比如用来取cookie值的 cookie_XXX 变量群,用来取请求头的 httpXXX变量群,以及用来取响应头的 sent_http_XXX 变量群。这里就不一一介绍了,感兴趣可以参考 ngx_http_core 模块的官方文档。
大部分内建变量都只是可读的,如果去赋值,会在启动nginx时报错
–
不是所有的 Nginx 变量都拥有存放值的容器。拥有值容器
的变量在 Nginx 核心中被称为“被索引的”(indexed);反之,则被称为“未索引的”(non-indexed)。$arg_xxx
就是未索引的变量。
在我们读取类似 $arg_xxx
内建变量群时,nginx会执行相应的读处理程序扫描URL的参数串去获取这个变量的值,$cookie_xxx
也是这样的.
–
http{
map $arg_method $ret {
GET 1;
POST 2;
PUT 3;
DELETE 4;
default 5;
}
server {
location /hi {
#set $arg_method get;
return 200 "ret:$ret";
}
}
这里我们使用了一个nginx中的map映射规则。这个map只能卸载http模块中,所以也就是全局的了。这里我们看一下请求情况
curl hongjian.cn/hi\?method=post
ret:2
curl hongjian.cn/hi\?method=POST
ret:2
这里我们可以看到,请求参数中的method,会按照map中的规则,映射为对应值,并且nginx会将参数转成小写后进行比较。
注意到上面的set语句是被注释掉的,这里我们将注释打开后,再次访问。
curl hongjian.cn/hi\?method=POST
ret:1
返回值变成了1,那这里就印证了一个事实,在取值(取ret)时,才会进行计算,这里我们称这种现象为惰性计算
。这里还看不到和缓存有什么关系,我们再做一个小调整。
http{
map $arg_method $ret {
GET 1;
POST 2;
PUT 3;
DELETE 4;
default 5;
}
server {
location /hi {
set $ret1 $ret;
set $arg_method default;
set $ret2 $ret;
return 200 "ret1:$ret, ret2:$ret2";
}
}
访问一下,查看请求结果
curl hongjian.cn/hi\?method=post
ret1:2, ret2:2
ret2
并没有因为我们将method变量设置为default而变化,这是为什么呢?原来,nginx可以为创建的变量选择值容器来作为缓存,ngx_map这种结构被认定计算耗费大,所以会进行缓存,因为惰性计算,只有在第一次执行对ret
的取程序时,才会计算ret的map结果,并将这个值作为缓存,所以之后我们就算修改了method
的值,下一条语句执行取程序时,还会返回上次缓存的结果。缓存值容器的声明周期是和请求相关联的
所以这种全局性的map结构,只有一个请求的第一次取程序执行时才会被计算一次,之后执行取程序时,会使用缓存结果。
比如set
赋值操作就会进行即时计算并将结果赋值给变量。
–
这里说的子请求并不是真正意义上的一个子HTTP请求,而是借助第三方模块,比如ngx_location发起的一个C语言的调用而已,父子请求间对于变量有共享也有非共享的,遇到之后再作具体查询和分析。