https://www.diewufeiyang.com/post/577.html

也有一些内建变量是支持改写的,其中一个例子是 $args. 这个变量在读取时返回当前请求的 URL 参数串(即请求 URL 中问号后面的部分,如果有的话 ),而在赋值时可以直接修改参数串。我们来看一个例子:

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

这里我们把原始的 URL 参数串先保存在 $orig_args 变量中,然后通过改写 $args 变量来修改当前的 URL 参数串,最后我们用 echo 指令分别输出 $orig_args 和 $args 变量的值。接下来我们这样来测试这个 /test 接口:

Bash
    $ 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

在第一次测试中,我们没有设置任何 URL 参数串,所以输出 $orig_args 变量的值时便得到空。而在第一次和第二次测试中,无论我们是否提供 URL 参数串,参数串都会在 location /test 中被强行改写成 a=3&b=4.

需要特别指出的是,这里的 $args 变量和 $arg_XXX 一样,也不再使用属于自己的存放值的容器。当我们读取 $args 时,Nginx 会执行一小段代码,从 Nginx 核心中专门存放当前 URL 参数串的位置去读取数据;而当我们改写 $args 时,Nginx 会执行另一小段代码,对相同位置进行改写。Nginx 的其他部分在需要当前 URL 参数串的时候,都会从那个位置去读数据,所以我们对 $args 的修改会影响到所有部分的功能。我们来看一个例子:

Bash
    location /test {
set $orig_a $arg_a;
set $args "a=5";
echo "original a: $orig_a";
echo "a: $arg_a";
}

这里我们先把内建变量 $arg_a 的值,即原始请求的 URL 参数 a 的值,保存在用户变量 $orig_a 中,然后通过对内建变量 $args 进行赋值,把当前请求的参数串改写为 a=5 ,最后再用 echo 指令分别输出 $orig_a 和 $arg_a 变量的值。因为对内建变量 $args 的修改会直接导致当前请求的 URL 参数串发生变化,因此内建变量 $arg_XXX 自然也会随之变化。测试的结果证实了这一点:

Bash
    $ curl 'http://localhost:8080/test?a=3'
original a: 3
a: 5

我们看到,因为原始请求的 URL 参数串是 a=3, 所以 $arg_a 最初的值为 3, 但随后通过改写 $args 变量,将 URL 参数串又强行修改为 a=5, 所以最终 $arg_a 的值又自动变为了 5.

我们再来看一个通过修改 $args 变量影响标准的 HTTP 代理模块 ngx_proxy 的例子:

Bash
    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";
}
}

这里我们在 http 配置块中定义了两个虚拟主机。第一个虚拟主机监听 8080 端口,其 /test 接口自己通过改写 $args 变量,将当前请求的 URL 参数串无条件地修改为 foo=1&bar=2. 然后 /test 接口再通过 ngx_proxy 模块的 proxy_pass 指令配置了一个反向代理,指向本机的 8081 端口上的 HTTP 服务 /args. 默认情况下,ngx_proxy 模块在转发 HTTP 请求到远方 HTTP 服务的时候,会自动把当前请求的 URL 参数串也转发到远方。

而本机的 8081 端口上的 HTTP 服务正是由我们定义的第二个虚拟主机来提供的。我们在第二个虚拟主机的 location /args 中利用 echo 指令输出当前请求的 URL 参数串,以检查 /test 接口通过 ngx_proxy 模块实际转发过来的 URL 请求参数串。

我们来实际访问一下第一个虚拟主机的 /test 接口:

Bash
    $ curl 'http://localhost:8080/test?blah=7'
args: foo=1&bar=2

我们看到,虽然请求自己提供了 URL 参数串 blah=7,但在 location /test 中,参数串被强行改写成了 foo=1&bar=2. 接着经由 proxy_pass 指令将我们被改写掉的参数串转发给了第二个虚拟主机上配置的 /args 接口,然后再把 /args 接口的 URL 参数串输出。事实证明,我们对 $args 变量的赋值操作,也成功影响到了 ngx_proxy 模块的行为。

在读取变量时执行的这段特殊代码,在 Nginx 中被称为“取处理程序”(get handler);而改写变量时执行的这段特殊代码,则被称为“存处理程序”(set handler)。不同的 Nginx 模块一般会为它们的变量准备不同的“存取处理程序”,从而让这些变量的行为充满魔法。

 

其实这种技巧在计算世界并不鲜见。比如在面向对象编程中,类的设计者一般不会把类的成员变量直接暴露给类的用户,而是另行提供两个方法(method),分别用于该成员变量的读操作和写操作,这两个方法常常被称为“存取器”(accessor)。下面是 C++ 语言中的一个例子:

Bash
    #include <string>
using namespace std;
class Person {
public:
const string get_name() {
return m_name;
} void set_name(const string name) {
m_name = name;
} private:
string m_name;
};

在这个名叫 Person 的 C++ 类中,我们提供了 get_name 和 set_name 这两个公共方法,以作为私有成员变量 m_name 的“存取器”。

这样设计的好处是显而易见的。类的设计者可以在“存取器”中执行任意代码,以实现所需的业务逻辑以及“副作用”,比如自动更新与当前成员变量存在依赖关系的其他成员变量,抑或是直接修改某个与当前对象相关联的数据库表中的对应字段。而对于后一种情况,也许“存取器”所对应的成员变量压根就不存在,或者即使存在,也顶多扮演着数据缓存的角色,以缓解被代理数据库的访问压力。

 

与面向对象编程中的“存取器”概念相对应,Nginx 变量也是支持绑定“存取处理程序”的。Nginx 模块在创建变量时,可以选择是否为变量分配存放值的容器,以及是否自己提供与读写操作相对应的“存取处理程序”。

不是所有的 Nginx 变量都拥有存放值的容器。拥有值容器的变量在 Nginx 核心中被称为“被索引的”(indexed);反之,则被称为“未索引的”(non-indexed)。

我们前面在 (二) 中已经知道,像 $arg_XXX 这样具有无数变种的变量群,是“未索引的”。当读取这样的变量时,其实是它的“取处理程序”在起作用,即实时扫描当前请求的 URL 参数串,提取出变量名所指定的 URL 参数的值。很多新手都会对 $arg_XXX 的实现方式产生误解,以为 Nginx 会事先解析好当前请求的所有 URL 参数,并且把相关的 $arg_XXX 变量的值都事先设置好。然而事实并非如此,Nginx 根本不会事先就解析好 URL 参数串,而是在用户读取某个 $arg_XXX 变量时,调用其“取处理程序”,即时去扫描 URL 参数串。类似地,内建变量 $cookie_XXX 也是通过它的“取处理程序”,即时去扫描 Cookie 请求头中的相关定义的。

【转帖】nginx变量使用方法详解-3的更多相关文章

  1. [转帖]Nginx rewrite模块深入浅出详解

    Nginx rewrite模块深入浅出详解 https://www.cnblogs.com/beyang/p/7832460.html rewrite模块(ngx_http_rewrite_modul ...

  2. [转帖]Nginx安装及配置详解 From https://www.cnblogs.com/zhouxinfei/p/7862285.html

    Nginx安装及配置详解   nginx概述 nginx是一款自由的.开源的.高性能的HTTP服务器和反向代理服务器:同时也是一个IMAP.POP3.SMTP代理服务器:nginx可以作为一个HTTP ...

  3. [转帖]nginx服务器安装及配置文件详解

    nginx服务器安装及配置文件详解 http://seanlook.com/2015/05/17/nginx-install-and-config/  发表于 2015-05-17 |  更新于: 2 ...

  4. [转帖]Vim编辑器使用方法详解

    Vim编辑器使用方法详解 程序员小新人学习 2018-12-16 12:26:23 转载于https://www.cnblogs.com/libaoliang/articles/6961676.htm ...

  5. Linux设置和查看环境变量的方法 详解

    1. 显示环境变量HOME $ echo $HOME /home/redbooks 2. 设置一个新的环境变量hello $ export HELLO="Hello!" $ ech ...

  6. Pythony的数据类型和变量使用方法详解

    数据类型:计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同的数据,需要定 ...

  7. Nginx服务器中配置非80端口的端口转发方法详解

    这篇文章主要介绍了Nginx服务器中配置非80端口的端口转发方法详解,文中使用到了Nginx中的proxy_pass配置项,需要的朋友可以参考下 nginx可以很方便的配置成反向代理服务器: 1 2 ...

  8. 2-4、nginx特性及基础概念-nginx web服务配置详解

    Nginx Nginx:engine X 调用了libevent:高性能的网络库 epoll():基于事件驱动event的网络库文件 Nginx的特性: 模块化设计.较好扩展性(不支持模块动态装卸载, ...

  9. 【第六课】Nginx常用配置下详解

    目录 Nginx常用配置下详解 1.Nginx虚拟主机 2.部署wordpress开源博客 3.部署discuz开源论坛 4.域名重定向 5.Nginx用户认证 6.Nginx访问日志配置 7.Ngi ...

  10. session的使用方法详解

    session的使用方法详解 Session是什么呢?简单来说就是服务器给客户端的一个编号.当一台WWW服务器运行时,可能有若干个用户浏览正在运正在这台服务器上的网站.当每个用户首次与这台WWW服务器 ...

随机推荐

  1. Python借助企业微信群机器人发送消息、图片和文件

    企业微信功能日益强大,腾讯官方也提供了丰富的API供开发者实现企业微信的很多自动化场景.比如,如何给某个企业微信群发送消息.图片或者文件,甚至@指定群用户?别急,看小爬君轻松教会大家. Step1:在 ...

  2. Text Intelligence - TextIn.com AI时代下的智能文档识别、处理、转换

    一.智能文档处理介绍 在AI时代,智能文档处理技术正变得越来越重要.它包括了智能文字识别(OCR).智能文档信息抽取.文档图像处理以及文档转换等多个方面.这些技术共同构成了现代信息处理的核心,广泛应用 ...

  3. SQL Server系列:系统函数之聚合函数

    聚合函数:指对一组值执行计算,并返回单个值.除了 Count(统计函数) 外,聚合函数都会忽略 Null 值 聚合函数经常与 SELECT 语句的 GROUP BY 子句一起使用 1.Avg():返回 ...

  4. 华为云分布式云原生UCS,助力MetaERP构建企业级高可用分布式业务

    本文分享自华为云社区<华为云分布式云原生UCS,助力MetaERP构建企业级高可用分布式业务>,作者:云容器大未来. 引言 华为云最近成为<Forrester Wave: Multi ...

  5. KubeEdge@MEC:Kubernetes容器生态与5G的结合

    摘要:边缘计算技术快速发展,5G MEC边云协同成为最新的发展趋势. 前言 边缘计算技术快速发展,5G MEC进入商业部署快车道,边云协同成为MEC的普遍诉求,KubeEdge社区洞悉这一趋势,按照C ...

  6. iOS IPA包的制作和上传步骤详解​

    目录 前言 一.IPA包的原理 二.IPA包上传的步骤 1.注册开发者账号 2.创建应用程序 3.编码和设计 4.生成证书和配置文件 5.打包IPA包 6.上传IPA包 三.总结 前言 iOS IPA ...

  7. Python pdf 转 图片

    安装依赖 D:\OpenSource\Python>pip install pdf2image pillow -i https://pypi.tuna.tsinghua.edu.cn/simpl ...

  8. -bash: /home/advert/bin/vim: No such file or directory

    今天advert用户使用vim时,突然报错 -bash: /home/advert/bin/vim: No such file or directory 之前还好好的,且其他用户都能用vim,查看也是 ...

  9. AcWing 第五场周赛

    比赛链接:Here AcWing 3726. 调整数组 签到题 void solve() { int n; cin >> n; int x = 0, y = 1, c; for (int ...

  10. CF(codeforces)如何保持紫名及以上?

    虽然我还是连绿名都没,但还是想学习大牛们的学习方法,加油尽早上分. 转自知乎 之前在 CF 上看到一条不错的评论 https://codeforces.com/blog/entry/66715?#co ...