openresty开发系列35--openresty执行流程之5内容content阶段

content 阶段

---init阶段---重写赋值---重写rewrite---access

content 阶段属于一个比较靠后的处理阶段,运行在先前介绍过的 rewrite 和 access 这两个阶段之后。
当和 rewrite、access 阶段的指令一起使用时,这个阶段的指令总是最后运行,例如:

location /content {
    # 重写阶段
    set $age 1;
    rewrite_by_lua "ngx.var.age = ngx.var.age + 1";

# 访问阶段
    deny 127.0.0.1;
    access_by_lua "ngx.var.age = ngx.var.age * 2";

# 内容阶段
    echo "age = $age";
}

启动nginx  ,访问 输出 age = 4

改变它们的书写顺序,也不会影响到执行顺序。其中,
set 指令来自 ngx_rewrite 模块,运行于 rewrite 阶段;
而 rewrite_by_lua 指令来自 ngx_lua 模块,运行于 rewrite 阶段的末尾;
接下来,deny 指令来自 ngx_access 模块,运行于 access 阶段;
再下来,access_by_lua 指令同样来自 ngx_lua 模块,运行于 access 阶段的末尾;

最后,echo 指令则来自 ngx_echo 模块,运行在 content 阶段

----------------------------------------------

一)content_by_lua

语法:content_by_lua <lua-script-str>
默认值:无
上下文:location, location if
说明:行为类似与一个“content handler”,给每个请求执行定义于lua-script-str中的lua code。
每一个 location 只能有一个“内容处理程序”,因此,当在 location 中同时使用多个模块的 content 阶段指令时,
只有其中一个模块能成功注册“内容处理程序”。例如这个指令和proxy_pass指令不能同时使用在相同的location中

--------------------------------

例中的 set 指令和 rewrite_by_lua 指令同处于 rewrite 阶段,
而 deny 指令和 access_by_lua 指令则同处于 access 阶段。
但不幸的是echo指令,不能同时content_by_lua处于 content 阶段。

考虑下面这个有问题的例子:

location /content1 {
 echo "hello ";
 content_by_lua 'ngx.say("world")';
}

访问 http://10.11.0.215/content1 输出 world

# 调换顺序
location /content1 {
 
 content_by_lua 'ngx.say("world")';
 echo "hello ";

}

访问 http://10.11.0.215/content1 输出 hello

这里,ngx_echo 模块的 echo 指令和 ngx_lua 模块的 content_by_lua 指令同处 content 阶段,
于是只有其中一个模块能注册和运行这个 location 的“内容处理程序”:

访问输出 world

输出了后面的 content_by_lua 指令;而 echo 指令则完全没有运行。
例中的 echo 语句和 content_by_lua 语句交换顺序,则输出就会变成 hello。
所以我们应当避免在同一个 location 中使用多个模块的 content 阶段指令。

location /content1 {
    echo hello;
    echo world;
}

这里使用多条 echo 指令是没问题的,因为它们同属 ngx_echo 模块,而且 ngx_echo模块规定和实现了它们之间的
执行顺序。并非所有模块的指令都支持在同一个 location 中被使用多次,例如 content_by_lua 就只能使用一次,
所以下面这个例子是错误的:

location /content1 {
  content_by_lua 'ngx.say("hello")';
  content_by_lua 'ngx.say("world")';
}

报错nginx: [emerg] "content_by_lua" directive is duplicate

正确写法:
location /content1 {
    content_by_lua 'ngx.say("hello") ngx.say("world")';
}

----------------------------------------------

二)如果一个 location 中未使用任何 content 阶段的指令,会如何处理?

静态资源服务模块

1) ngx_index
2) ngx_autoindex
3) ngx_static

location /content {
    
}

nginx会把当前请求的 URI 映射到文件系统的静态资源服务模块。
当存在“内容处理程序”时,这些静态资源服务模块并不会起作用;反之,请求的处理权就会自动落到这些模块上。

Nginx 一般会在 content 阶段安排三个这样的静态资源服务模块(除非你的 Nginx 在构造时显式禁用了这三个模块中
的一个或者多个,又或者启用了这种类型的其他模块)。按照它们在 content 阶段的运行顺序,依次是 ngx_index
模块,ngx_autoindex 模块,以及 ngx_static 模块。

下面就来逐一介绍一下这三个模块

ngx_index 和 ngx_autoindex 模块都只会作用于那些 URI 以 / 结尾的请求
 例如请求 GET /cats/,而对于不以 / 结尾的请求则会直接忽略,同时把处理权移交给 content 阶段的下一个模块。

而 ngx_static 模块则刚好相反,直接忽略那些 URI 以 / 结尾的请求。

以 / 结尾的请求   ===》  ngx_index 和 ngx_autoindex 模块 进行处理

不以 / 结尾的请求   ===》  ngx_static 进行处理

1) ngx_index 模块

主要用于在文件系统目录中自动查找指定的首页文件,类似 index.html 和 index.htm 这样的,
 例如:

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

当用户请求 / 地址时,Nginx 就会自动在 root 配置指令指定的文件系统目录下依次寻找 index.htm 和 index.html
这两个文件。如果 index.htm 文件存在,则直接发起“内部跳转”到 /index.htm 这个新的地址;
而如果 index.htm 文件不存在,则继续检查 index.html 是否存在。如果存在,同样发起“内部跳转”到 /index.html;
如果 index.html 文件仍然不存在,则放弃处理权给 content 阶段的下一个模块。

内部跳转:rewrite last 内容跳转
------------------------------------------

验证 ngx_index 模块在找到文件时的“内部跳转”行为,看下面的例子

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

location /index.html {
    set $a 32;
    echo "a = $a";
}

输出 a = 32

为什么输出不是 index.html 文件的内容?首先对于用户的原始请求 GET /,Nginx 匹配出 location / 来处理它,
然后 content 阶段的 ngx_index 模块在 html 下找到了 index.html,于是立即发起一个到 /index.html
位置的“内部跳转”。在重新为 /index.html 这个新位置匹配 location 配置块时,
location /index.html 的优先级要高于 location /,因为 location 块按照 URI 前缀来匹配时遵循所谓的
“最长子串匹配语义”。这样,在进入 location /index.html 配置块之后,又重新开始执行 rewrite 、access、
以及 content 等阶段。最终输出 a = 32

-------------------

如果此时把 /html/index.html 文件删除,再访问 / 又会发生什么事情呢?
答案是返回 403 Forbidden 出错页。

为什么呢?因为 ngx_index 模块找不到 index 指令指定的文件index.html,
接着把处理权转给 content 阶段的后续模块,而后续的模块也都无法处理这个请求,
于是 Nginx 只好放弃,输出了错误页,并且在 Nginx 错误日志中留下了类似这一行信息:

[error] 28789#0: *1 directory index of "/html/" is forbidden

------------------
2) ngx_autoindex 模块
所谓 directory index 便是生成“目录索引”的意思,典型的方式就是生成一个网页,
上面列举出 /html/ 目录下的所有文件和子目录。而运行在 ngx_index 模块之后的
ngx_autoindex 模块就可以用于自动生成这样的“目录索引”网页。我们来把上例修改一下:

location / {
        root /html/;
        index index.html;
        autoindex on;
    }
此时仍然保持文件系统中的 /html/index.html 文件不存在。我们再访问 / 位置时,就会得到目录下的文件列表

---------------------
3)ngx_static 模块
在 content 阶段默认“垫底”的最后一个模块便是极为常用的 ngx_static 模块。

这个模块主要实现服务静态文件的功能。比方说,一个网站的静态资源,包括静态 .html 文件、静态 .css 文件、
静态 .js 文件、以及静态图片文件等等,全部可以通过这个模块对外服务。

前面介绍的 ngx_index 模块虽然可以在指定的首页文件存在时发起“内部跳转”,但真正把相应的首页文件服务出去
(即把该文件的内容作为响应体数据输出,并设置相应的响应头),还是得靠这个 ngx_static 模块来完成。

---------------------

在下面例子

location / {
    root html;
}

在html目录下创建hello.html文件

访问http://10.11.0.215/hello.html

不妨来分析一下这里发生的事情:location / 中没有使用运行在 content 阶段的模块指令,
于是也就没有模块注册这个 location 的“内容处理程序”,处理权便自动落到了在 content 阶段“垫底”的
那 3 个静态资源服务模块。

a)首先运行的 ngx_index 和 ngx_autoindex 模块先后看到当前请求的 URI,/hello.html,并不以 / 结尾,
于是直接弃权,
b)将处理权转给了最后运行的 ngx_static 模块。ngx_static 模块根据 root 指令指定的“文档根目录”
(document root),分别将请求 /hello.html 映射为文件系统路径 /html/hello.html,在确认这个文件存在后,
将它们的内容分别作为响应体输出,并自动设置 Content-Type、Content-Length 以及 Last-Modified 等响应头。

转载于:https://www.cnblogs.com/reblue520/p/11446470.html

openresty开发系列35--openresty执行流程之5内容content阶段相关推荐

  1. openresty开发系列36--openresty执行流程之6日志模块处理阶段

    openresty开发系列36--openresty执行流程之6日志模块处理阶段 一)header_filter_by_lua 语法:header_filter_by_lua <lua-scri ...

  2. openresty开发系列34--openresty执行流程之4访问阶段

    openresty开发系列34--openresty执行流程之4访问阶段 访问阶段 用途:访问权限限制 返回403 nginx:allow 允许,deny 禁止 allow ip: deny ip: ...

  3. openresty开发系列33--openresty执行流程之3重写rewrite和重定向

    openresty开发系列33--openresty执行流程之3重写rewrite和重定向 重写rewrite阶段 1)重定向 2)内部,伪静态 先介绍一下if,rewrite指令 一)if指令 语法 ...

  4. openresty开发系列33--openresty执行流程之2重写赋值阶段

    openresty开发系列33--openresty执行流程之2重写赋值阶段 一)重写赋值阶段 1)set_by_lua 语法:set_by_lua $res <lua-script-str&g ...

  5. openresty开发系列32--openresty执行流程之1初始化阶段

    openresty开发系列32--openresty执行流程之初始化阶段 一)初始化阶段 1)init_by_lua   init_by_lua_block     init_by_lua_file ...

  6. openresty开发系列2--nginx的简单安装,正向、反向代理及常用命令和信号控制介绍...

    openresty开发系列2--nginx的简单安装,正向.反向代理及常用命令和信号控制介绍 一.nginx的安装下载及编译安装 1.Nginx下载:nginx-1.13.0.tar.gz,下载到:/ ...

  7. openresty开发系列40--nginx+lua实现获取客户端ip所在的国家信息

    openresty开发系列40--nginx+lua实现获取客户端ip所在的国家信息 为了实现业务系统针对不同地区IP访问,展示包含不同地区信息的业务交互界面.很多情况下系统需要根据用户访问的IP信息 ...

  8. openresty开发系列38--通过Lua+Redis 实现动态封禁IP

    openresty开发系列38--通过Lua+Redis 实现动态封禁IP 一)需求背景为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单.对于黑名单之内的 IP ,拒绝 ...

  9. openresty开发系列37--nginx-lua-redis实现访问频率控制

    openresty开发系列37--nginx-lua-redis实现访问频率控制 一)需求背景 在高并发场景下为了防止某个访问ip访问的频率过高,有时候会需要控制用户的访问频次 在openresty中 ...

最新文章

  1. echarts的词云图表类型有哪些_词云图的几种制作方法评测,你pick哪款
  2. python列拼接dataframe_如何将两个dataframe中的两列合并为新dataframe(pandas)的一列?...
  3. 为企业提供本地销售人员的Universal Avenue获1000万美元A轮融资
  4. java写一个服务定时采集数据_java实现定时任务解决方案
  5. curl 常用的命令
  6. java 把文件转化为字节数组
  7. VS2015新建项目无法选择framework 4.6.2
  8. 数据拟合---使用自定义函数进行非线性拟合 -在Origin。matlab拟合工具箱cftool
  9. fatfs文件系统f_lseek追加文件
  10. Windows下解压tar.gz压缩文件
  11. VS下使用多字符集编码和Unicode字符集编码的总结
  12. 2018中国企业云计算应用现状及需求调研报告
  13. xxx.so has text relocations. This is wasting memory and is a security risk. Please fix
  14. win10 NET Framework 3.5(包括.NET 2.0和3.0)错误代码0x800f081f 的解决方法
  15. AliOS-Things--Visual Studio Code Windows环境搭建 EMW3060
  16. python统计一组数据中的概率_Python实现概率分布
  17. 极米NEW Z6X和坚果G9哪个好?
  18. 北京化工大学计算机复试面试题,北京化工大学综合素质测试面试题历年总结
  19. [安装fastfds中的nginx执行make命令报错]src/core/ngx_murmurhash.c:37:11: error
  20. NCTF2020 web 你就是我的master吗

热门文章

  1. h3c服务器安装linux,H3C服务器安装Ubuntu操作系统
  2. JVM监控及诊断工具-命令行篇一
  3. linux 安装 加入内核参数,Linux 实现自动安装服务组件以及优化内核参数
  4. 串口服务器怎么测信号,串口服务器如何调试
  5. django 不用自带的mysql_python笔记二 django自带后台管理系统、模版渲染以及使用mysql数据库...
  6. 【实验】配置802.1x远端认证
  7. 混合云应用双活容灾实践
  8. 如何基于 K8s 构建下一代 DevOps 平台?
  9. 从零开始入门 K8s | 理解 RuntimeClass 与使用多容器运行时
  10. python只能对列表进行切片_Python3:类型错误:列表索引必须是整数或切片,而不是s...