继续上一篇的分析,下面我们将主要谈论set和rewrite两行的解析处理。为了方便分析,这里把示例配置和调用图列出来
location / {
if ($uri ~* "(.*).html$" ) {
set $file $1;
rewrite ^(.*)$ http://$http_host$file.mp4 break;
}
}

(一) set行的解析
1. 我们首先看这里这句:
ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE);
为什么这个函数的第三个参数flag,被设置成NGX_HTTP_VAR_CHANGEABLE,那是因为set之后的第一个的变量可以在一个if配置里面出现多次,每次可以改变它的值,当然还有nochangeable的,后面碰到再说。紧接着,把这个变量放到全局变量数组中,同时记录它的所在位置(即下标index),即函数ngx_http_get_variable_index。
2. 通过图中所示,先处理的是set后面的第二个变量,那第一个怎么办呢?先处理它使用原因的,一会就可以看到了。这个变量通过ngx_http_rewrite_value函数来处理的,在处理时带有$的变量,nginx里面称作“complex value”,于是分配ngx_http_script_complex_value_code_t结构同时使用ngx_http_script_complex_value_code来处理,接下来有几行代码需要注意下:
// lengths和values数组会在ngx_http_script_compile的执行过程中被填充
sc.lengths = &complex->lengths;
sc.values = &lcf->codes;
// complete_lengths置1,是为了给lengths数组结尾(以null指针填充),因为在运
// 行这个数组中的成员时,碰到NULL时,执行就结束了。
sc.complete_lengths = 1;
3. ngx_http_script_compile函数算是这里的一个核心,主要是分离当前“complex value”中的一些不同类型的变量,具体逻辑不难看懂,我们只把一些需要注意的地方强调下就行了。
在开始的时候有个函数叫ngx_http_script_init_arrays,这个函数对flushes,lengths和values三个数组的初始容量给出了一个估计值,当然nginx的数组结构在初始空间不够的时候会自动扩充的,这个就不用太追究了。
在函数ngx_http_script_add_capture_code中,有个这样的赋值动作code->n = 2 * n,为什么是2*n呢?这个跟PCRE保存匹配结果集的结构有关,后面我们会讲到。
4. 在处理set 中的第一个参数的时候,它的handler被置为了ngx_http_script_set_var_code,通过这个函数,我们也就知道了为什么要先处理后一个参数:
// e->ip就是之前在解析时设置的各种结构体
code = (ngx_http_script_var_code_t *) e->ip;
e->ip += sizeof(ngx_http_script_var_code_t);
r = e->request;
// e->sp是通过解析得到的变量处理结果的一个数组,变量的放置顺序跟
// ip中的顺序一致,而且随着处理而递增,所以为了保持中处理的一致性(这样
// 就可以保证许多地方使用一致的处理方式)。这里sp—就可以得到之前的处
// 理值,得到我们想要的结果了。
e->sp--;
r->variables[code->index].len = e->sp->len;
r->variables[code->index].valid = 1;
r->variables[code->index].no_cacheable = 0;
r->variables[code->index].not_found = 0;
r->variables[code->index].data = e->sp->data;
(二) rewrite行的解析
有了前面对if和set的介绍,rewrite分析起来就简单多了,大多数的处理前面都已经出现过了,这里只说几个重点。
1. 在rewrite后面第二个参数中,凡是以“http://”,“https://”,“$scheme”,或者是最后的参数是“redirect”的,在后续的处理都是产生302的响应,其次最后的参数里,如“permanent”会产生301响应,last和break将会产生nginx内部的重定向(相当于重新做一次http的请求),会重新进行location的匹配等,但是它们的区别在于break在重定向时,就不会在做重定向的处理,而last将会继续。
2. 对于rewrite后面第二个参数的处理,跟处理set中第二个变量的过程是大致一样的。需要强调的有以下几点:
// 刚开始的时候已经给regex做了初始化,为什么后面有重新赋值了一次呢?原因就是“它可能变了”。。。
regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
sizeof(ngx_http_script_regex_code_t));
…
regex = sc.main;
对于上面这个问题,可以追溯到ngx_http_script_add_code函数,我们知道nginx在对数组push时,如果发现空间不足会做扩充,在扩充时会分配原来两倍大小的空间,并把原有数据copy过来。这样一样原来执行这个数组中的一些指针值此时就不能再用了,而要指向他们的“新家”,这也就是这里regex重新赋值以及以®ex为参数传递给ngx_http_script_add_code的目的所在。
3. 到这里我们的if指令到了结束的时候,那么就以一个NULL来做结尾。
if (last) {
code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), ®ex);
if (code == NULL) {
return NGX_CONF_ERROR;
}
*code = NULL;
}
看最后这一句:
regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts - (u_char *) regex;
这里其实说明了当前位置距离codes数组的大小,这样在必要的时候,例如e->ip += code->next,跳过当前结构去处理下一个,很方便。
到这里,基本的轮廓就是这样子,至于各个handler的执行细节,大家可以自己去阅读代码,提示一点的是,要结合e->ip,e->sp等,ngx_http_script_engine_t结构中的一些成员来看,就容易懂了。
下一篇,我们针对脚本解析这块涉及的一些细节,做下探讨,来结束这块的分析
分享到:
相关推荐
### Nginx脚本引擎与Rewrite设计原理深入解析 #### 一、Set语句的解析与处理 在深入探讨Nginx脚本引擎与Rewrite设计原理时,我们聚焦于`set`与`rewrite`指令的处理机制,这两者在Nginx的配置文件中极为常见,尤其...
Nginx的脚本引擎设计精妙,尽管无法与专业级脚本语言媲美,但其高抽象性和灵活性足以满足web服务的需求。在配置解析过程中,Nginx会为每个配置项创建一个包含关键信息的结构体,并关联相应的处理函数(handler)。...
### Nginx脚本引擎与Rewrite设计原理详解 #### 一、引言 Nginx作为一款高性能的Web服务器及反向代理服务器,在互联网领域得到了广泛应用。其强大的功能不仅体现在高并发处理能力上,还在于灵活的配置选项以及丰富的...
**Nginx脚本详解** Nginx,作为一款高性能的HTTP和反向代理服务器,以其轻量级、高并发的特性在Web服务领域广泛应用。它不仅能够处理静态内容,还可以通过配置执行一些动态处理任务,例如使用脚本来实现自定义逻辑...
**Nginx 一键安装与自动化脚本** 在IT行业中,服务器配置和管理是一项重要的任务,尤其是在处理Web服务时。Nginx是一款高性能的HTTP和反向代理服务器,以其高效、稳定和轻量级的特性而广受欢迎。本文将详细讨论如何...
**Nginx添加站点脚本详解** 在Web服务器领域,Nginx以其高性能、轻量级和高并发处理能力而闻名。Nginx通过配置不同的站点来管理多个网站的运行,而“添加站点脚本”就是一种自动化创建和管理Nginx站点配置的工具。...
要创建一个自动化安装Nginx的脚本,你需要熟悉bash shell语法,包括变量、条件语句、循环以及函数等概念。 1. **安装必备工具**:在开始安装Nginx之前,确保系统已经安装了必要的软件包管理器,如`apt`(Ubuntu/...
对于“源码”部分,脚本可能涉及到检查Nginx是否已运行、设置环境变量、处理命令行参数、调用Nginx二进制文件以及处理各种信号等。 “工具”可能指的是使用`systemctl`、`service`或`init.d`命令来管理Nginx服务,...
5. **变量与上下文**:ngx_ruby支持Nginx内置变量,如`$request_uri`,同时也可以创建自己的变量。这些变量可以在不同的`ruby`块之间共享,形成一个共享的上下文。 6. **性能优化**:虽然Ruby语言本身较动态,但...
### Bash脚本示例:Nginx服务状态检查与操作 #### 概述 本文将详细介绍一个用于管理和检查Nginx服务状态的Bash脚本。该脚本能够自动检测Nginx服务是否正在运行,并根据当前状态执行启动、停止或重启等操作。通过这...
7. **权限与安全**:确保脚本有正确的执行权限,并且在处理敏感信息(如邮件凭据)时遵循安全最佳实践,比如使用环境变量存储密码,而非直接写入脚本。 8. **日志记录**:脚本执行过程中的信息(如检查结果、发送...
这里给大家介绍一个很好用的nginx启动脚本。以及简单的使用,如下: 1. 执行如下命令: vim /etc/init.d/nginxd 2.输入如下内容: 注意:该文件中的如下几个变量,都需要根据你实际的目录来改写。 nginx=/usr/...
14. OpenResty:标签中提到了openresty,这表明教程可能也会涉及到OpenResty的相关知识,OpenResty是一个基于Nginx和LuaJIT的高性能Web平台,它将Nginx与Lua脚本语言结合,从而提供了丰富的扩展性和开发上的便利。...
Linux下创建Nginx脚本以实现启动(start)、停止(stop)、重载(reload)等操作的详细知识点介绍: 1. Nginx的基本概念与作用: Nginx是一款高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP代理服务器。它以...
3. **变量与控制结构**:Lua支持基本的数据类型(字符串、数字、表等)和控制流程(if、for、while等),方便编写复杂逻辑。 4. **错误处理**:通过`ngx.exit()`或`ngx.log()`处理异常,确保Nginx正常运行。 ### ...
Lua的设计目标是为了提高效率与可扩展性,在游戏开发、网络应用等领域有着广泛的应用。 - **OpenResty**:是一个基于Nginx与Lua的高性能Web平台,它极大地简化了在Nginx上编写复杂的Web应用的过程。OpenResty提供了...
此外,脚本还包含了一些辅助功能,比如检查网络是否已启用(`[ "$NETWORKING" = "no" ] && exit 0`),读取`/etc/sysconfig/nginx`中的配置变量,以及定义了一个锁文件`/var/lock/subsys/nginx`,用于标识服务是否...
本资源包含的是 Nginx 1.9.0 版本在 Windows 64 位系统上的安装与配置指南,以及用于管理 Nginx 服务的批处理脚本。 一、Nginx 1.9.0 安装 1. 下载:首先需要下载适用于 Windows 64 位系统的 Nginx 1.9.0 安装包。...
`pidfile` 变量指定了Nginx进程ID的文件位置,这对于管理和跟踪Nginx进程至关重要。 在脚本中,定义了几个主要的函数,如 `start`、`stop`、`restart`、`reload` 和 `force_reload`,分别对应启动、停止、重启、...