nginx的脚本引擎(一)

nginx的脚本的语法和shell是很像的,我大致看了一下觉得挺有意思的,就想写写记录一下。我没看过shell脚本的引擎,不知道nginx脚本引擎和shell脚本引擎像不像,但是我觉得nginx的脚本引擎有点像C和汇编。

ngx_http_script_engine_t这个结构就代表了一段脚本,ip指向的是编译好的脚本,sp指向的是一块内存用来存储脚本运行的时候产生的一些中间值。ip/sp从名字看就已经很像汇编了instruction pointer/stack pointer指令寄存器和栈寄存器呀,当然是我瞎猜的,有时间的话可以查一下官方文档。代码段里的各个指令长度不一定相同。

再来说说编译过程,编译过程是在nginx_http_script_engine_t建立之前执行的,我先画出了整个图是为了更好理解。举个set指令编译的的例子,比如你在脚本里有这样的代码set $foo helloworld,脚本编译的步骤如下:

第一步:首先在cmcf->variables_keys和cmcf->variables里增加一个变量foo,这个变量是可写的。我之前写的nginx的变量系统里只说了变量的读取方法,差别不大。

第二步:把ngx_http_script_value_code_t指令放到代码段里(code字段是一个回调函数,赋值成ngx_http_script_value_code),把ngx_http_script_var_code_t指令放到代码段里(code字段是一个回调函数,赋值成ngx_http_script_set_var_code)。

第三步:http请求来的时候会在rewrite阶段按顺序执行ip指向的这一段代码,也就是执行ngx_http_script_value_code和ngx_http_script_set_var_code函数。

我们看一下这两个函数做了什么

void
ngx_http_script_value_code(ngx_http_script_engine_t *e)
{ngx_http_script_value_code_t  *code;code = (ngx_http_script_value_code_t *) e->ip;e->ip += sizeof(ngx_http_script_value_code_t);e->sp->len = code->text_len;e->sp->data = (u_char *) code->text_data;ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,"http script value: \"%v\"", e->sp);e->sp++;
}
void
ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
{ngx_http_request_t          *r;ngx_http_script_var_code_t  *code;code = (ngx_http_script_var_code_t *) e->ip;e->ip += sizeof(ngx_http_script_var_code_t);r = e->request;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;
}

第一条指令把“helloworld”这个字符串放到了sp里,第二条指令把值从sp里取出来存到了变量系统的foo变量里,任务完成,看起来很简单。

set指令还可以这样用set $foo $x$y,这就是所谓的变量插值,过程和上面这个类似,只不过第一条指令是先从变量系统里取出$x和$y的值,再放入sp里。

其他指令和set指令的执行过程类似,把我看到的也写一下吧

if指令:同样举个最简单的例子if( $host = "www.foo.com" ),编译的时候依次把ngx_http_script_var_code/ngx_http_script_value_code_t/ngx_http_script_equal_code/ngx_http_script_if_code四条指令放到代码段里。脚本运行的时候这几条指令的工作分别是ngx_http_script_var_code把变量host的值取出来放到sp里。ngx_http_script_value_code_t把字符串“www.foo.com”放到sp里。ngx_http_script_equal_code比较sp里存的两个值是否相等并把两个值清除掉,相等就在sp里写入“1”,不相等就写入“0”(比较完以后这两个值就没用了,清除掉这两个值并且写入结果很像C里函数调用的过程)。ngx_http_script_if_code检查sp里的值是不是“0”,不是“0”说明条件为真继续执行之后的脚本,是“0”说明条件为假就会跳过这一段代码执行ngx_http_script_if_code_t结构里next偏移之后的代码。所有的代码都是在一个代码段里,不会因为有if把代码做嵌套,只不过会用next跳来跳去。

有一点需要注意如果if在location里if体里可以做一些location的配置,比如root之类的。当NGX_HTTP_REWRITE_PHASE阶段执行脚本的时候会把新的loc_conf赋值给r->loc_conf,这个一定要注意是NGX_HTTP_REWRITE_PHASE阶段而不是NGX_HTTP_FIND_CONFIG_PHASE阶段,设置loc_conf一般情况是在NGX_HTTP_FIND_CONFIG_PHASE阶段,但是这次不是。

void
ngx_http_script_if_code(ngx_http_script_engine_t *e)
{ngx_http_script_if_code_t  *code;code = (ngx_http_script_if_code_t *) e->ip;ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,"http script if");e->sp--;if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {if (code->loc_conf) {e->request->loc_conf = code->loc_conf;ngx_http_update_location_config(e->request);}e->ip += sizeof(ngx_http_script_if_code_t);return;}ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,"http script if: false");e->ip += code->next;
}

return指令:这个是比较简单的,脚本执行到这个指令就直接返回了,参数了可以带数据,例如return 200 helloworld,此外还可以重定向return 302 http://www.nginx.org。

break指令:粗暴的结束目前的脚本,但是有一点要注意,如果break指令在location里面,他并不会影响location其他字段的设置,因为他们在不同的阶段执行。比如说设置如下的配置文件

        location / {root html;break;index index.html;}

 这一点都不会影响你的index指令,他们不在同一阶段,index是在NGX_HTTP_FIND_CONFIG_PHASE阶段break是在NGX_HTTP_REWRITE_PHASE阶段,就像if指令里说的那样。

rewrite指令:这个略显麻烦,但是道理是一样的,休息,明天接着写。

转载于:https://www.cnblogs.com/4a8a08f09d37b73795649038408b5f33/p/9985528.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/450630.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个待办事列表todolist

最近有位老师让我做的,图片在下面,做了4个多小时,ui有的简陋,可以再美化一下,这个会更好看,毕竟我也不是专业前端,测试网站http://todolist.sshouxin.top/使用的是thinkphp5.1的框架&#xff0c…

详细说明 SourceTree 免登录,跳过初始设置的方法(Windows 版 )

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 1. 首先,安装完 SourceTree 以后先运行一次,弹出初始化登录页面后退出。 2. 进入这个文件夹:C:\Users…

Linux学习记录-文件、目录与磁盘

用户和群组 用户和群组主要是为了区分用户对文件的操作权限。 账号在/etc/passwd个人密码在/etc/shadow组信息在/etc/group 不要乱动这3个文件文件权限和目录配置 文件属性 文件前缀解释,例如: 第一个字符代表这个文件是『目录、文件或链接文件等等』&am…

解决 error: Your local changes to the following files would be overwritten by merge:XXXX

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 idea 上将本地代码推送到 git后 , 报错如下图 error: Your local changes to the following files would be overwritten by merge:src/…

数据库小知识点(一直更新)

一、mysql查询是否含有某字段: mysql数据库查询带有某个字段的所有表名 SELECT * FROM information_schema.columns WHERE column_namecolumn_name; oracle数据库查询带有某个字段的所有表名 select column_name,table_name,from user_tab_columns where column_n…

git pull --rebase 做了什么? 以及 Cannot rebase: You have unstaged changes 解决办法

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 最近刚学 git rebase,觉得很牛逼的样子, 结果今天就被打脸了。 git pull --rebase 1 报错: Cann…

vue如何实现单页缓存方案分析

实现全站的页面缓存,前进刷新,返回走缓存,并且能记住上一页的滚动位置,参考了很多技术实现,github上的导航组件实现的原理要么使用的keep-alive,要么参考了keep-alive的源码,但是只用keep-alive…

基于websocket的聊天实现逻辑(springboot)

websocket的知识点:当用户建立socket连接请求之后,服务器会给客户段建一个session(非httpsession),这是是对客户端的唯一识别码,用于消息通信 第二上流程图,流程图解释:用户1要给用户2发送消息…

大学生学编程系列」第五篇:自学编程需要多久才能找到工作?

很多编程初学者都会有这种疑问,自学学到什么程度或者学多久能够找到工作,这种问题没有统一答案,因为每个人的出发时候的基础以及在学习过程中掌握的程度不尽相同,也会导致结果不一样,只能说要看个人的造化了&#xff0…

chrome 谷歌浏览器怎么添加Axure扩展

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 工具/原料 谷歌浏览器Axure RP Extension for Chrome方法/步骤 百度搜索Axure RP,下载Axure RP,并进行安装 安装后…

配置nginx-rtmp流媒体服务器(宝塔面板配置教程)

参考文档:https://www.kancloud.cn/jiangguowu/kfjsdkfjskd/1209896 1.在宝塔面板中安装带nginx的服务器 2.在宝塔面板中卸载nginx(因为nginx-rtmp和nginx的配置不同,并且宝塔面板中不支持安装nginx-rtmp) 3.开始预下载nginx &a…

css控制div等比高度

在移动端开发中,在banner轮播图未加载出来之前,banner层是不占文档流高度的,当从服务器获取完banner数据,展示的时候,banner层因为有了内容 所以会撑开,导致banner层下面的内容也随之移动,为解决…

2018杭州云栖大会,梁胜博士的演讲PPT来啦!

2019独角兽企业重金招聘Python工程师标准>>> 2018杭州云栖大会已经结束,Rancher作为阿里云的紧密合作伙伴,Rancher Labs联合创始人兼CEO梁胜博士,在9月21日上午受邀出席大会并作题为**“如何能让每个人都用Kubernetes和Service Me…

利用jquery修改elment的自定义组件多选框el-select(修改多选框的颜色)

先上图片 一实现逻辑 我们知道element颜色默认为灰色,首先便签名称是唯一的,我的实现逻辑是后端传给前端 含有颜色,名称的数组,然后vue记录一个对象{名称 > 颜色},当用户选择标签之后,触发 点击事件&…

中文地址

2019独角兽企业重金招聘Python工程师标准>>> 转载于:https://my.oschina.net/u/2935389/blog/2209087

Intellij IDEA Debug调试技巧

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 1、这里以一个web工程为例,点击图中按钮开始运行web工程。 2、设置断点 3、使用postman发送http请求 4、请求发送之后会自动…

15行代码让苹果设备崩溃,最新的iOS 12也无法幸免

安全研究人员Sabri Haddouche发现了一个只需几行代码就可以让iPhone崩溃并重启的方法。\\Sabri Haddouche在GitHub上发布了一个示例网页,只有15行代码,如果在iPhone或iPad上访问这个页面,就会崩溃并重启。在macOS上使用Safari打开该页面也会出…

appium更新到1.8.2,不能打开运行的解决办法

1、更新下载appium 1.8.2 打开运行 一直是这个界面。很烦躁,重启电脑或者卸载后重新安装还是没有用。 解决版本: 1、查看老版本和新版本的安装位置 老版本默认是 C:\Program Files (x86)/appium安装新的版本后,地址是:C:\Users…

laraval如何使用tdd

1.首先新建一个laravel birdboard项目 composer create-project --prefer-dist birdboard 2.新建单元测试 php artisan make:test ProjectTest 3.书写单元测试 对于初学着来说,最好先预测tdd即将要出现的错误,然后进行测试,判断是否和自…

spring-data-JPA使用JpaRepository注解自定义SQL查询数据库多表查询

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 一. 首先在Entity注解的类里面要写好外键关系. 这个 ManyToOne 注解可以建立外键关系, 不要在自己傻傻的写一个 private int grades_id…