上一篇文章我写了 Nginx 的 11 个阶段,很多人都说太长了。这是出于文章完整性的考虑的,11 个阶段嘛,一次性说完就完事了。今天这篇文章比较短,看完没问题。

过滤模块的位置

之前我们介绍了 Nginx 的 11 个阶段,在 content 阶段时,Nginx 会生成返回给用户的响应内容,对用户的响应内容,实际上还需要做再加工处理,Nginx 的过滤模块就是对响应内容进行再加工处理的。所以实际上过滤模块位于 content 阶段之后,log 阶段之前。

我们先来看一段配置指令:

limit_req zone=req_one
burst=120;
limit_conn c_zone 1; satisfy any;
allow 192.168.1.0/32;
auth_basic_user_file access.pass; gzip on;
image_filter resize 80 80;

那么在这一段配置指令之下,会遵循怎样的请求流程呢?请看一下下面这张图:

上面这张图的流程大致说一下,如果对于 Nginx 的 11 个阶段不了解的去翻一下之前的文章。

我这里再简单说一下。首先由 Nginx 框架接收 HTTP 请求,经过 preaccess、access、content 阶段的处理,当经过 static 模块之后生成响应的时候,很多时候需要对响应进行处理,然后才会返回给客户端。

这里我们假如响应是一张图片的话,那么需要做缩略图的时候,首先就要经过 image_filter 模块的处理。这里面还有一个 gzip 模块,这两个模块也是需要遵循严格的顺序的。因为如果先做 gzip 压缩的话,缩略图后面就没办法做了。

第二个需要关注的地方是,首先对 header 进行过滤,再对 body 进行过滤。因为我们在对用户发送响应的时候,一定是先发送 header,然后再发送 body,所以所有的过滤模块都会提供对 header 或 body 的过滤,当然 image_filter 和 gzip 模块对这两者都可以过滤。

返回响应

前面我们说过,Nginx 的 11 个阶段是有严格的顺序的,而这个顺序是在 Nginx 的代码中以一个数组的形式存在的,这个数组的顺序是从后往前。在给用户返回响应的时候,过滤模块也是有严格顺序的,这个顺序同样是从后往前。来看一下在代码中的定义,标红的是我下面会提到的几个过滤模块。

我们需要重点关注四个过滤模块,它们分别的作用是啥呢?

  • copy_filter:复制包体内容

    当我们使用 sendfile 指令的时候,也就是零拷贝技术,不经过用户态内存,这里就是不经过 Nginx 直接发给用户,同时也用了 gzip 模块的时候,gzip 是必须在 copy_filter 模块之后的,因为 gzip 必须对内存中的数据做压缩,这时 copy_filter 就会让 sendfile 指令失效。有些模块不需要对内存中的数据进行处理,就需要在 copy_filter 模块之前进行处理。

  • postpone_filter:处理子请求

    用来处理子请求,有些过滤模块需要关心子请求的处理结果,需要放在该模块之后。

  • header_filter:构造响应头部

    用来构造最终发送给用户的响应头部,可能会添加一些 Server,Nginx 版本号等内容。

  • write_filter:发送响应

    用来实际调用操作系统的 write 或 send 等系统调用,来把响应实际发送出去。

介绍完了过滤模块的功能以及所处的阶段,下面来具体看两个模块。

sub 模块

介绍一个可以替换响应中字符串内容的模块:sub 模块。

  • 功能:将响应中指定的字符串,替换成新的字符串
  • 模块:ngx_http_sub_filter_module 模块,默认未编译进 Nginx,通过 --with-http_sub_module 启用

指令

Syntax: sub_filter string replacement;
Default: —
Context: http, server, location Syntax: sub_filter_last_modified on | off;
Default: sub_filter_last_modified off;
Context: http, server, location Syntax: sub_filter_once on | off;
Default: sub_filter_once on;
Context: http, server, location Syntax: sub_filter_types mime-type ...;
Default: sub_filter_types text/html;
Context: http, server, location

来解释一下这四个指令都是啥意思。

  • sub_filter string replacement

    sub_filter 指令会把匹配到的 string 字符串替换成 replacement 表示的字符串。

  • sub_filter_last_modified on | off

    sub_filter_last_modified 指令的意思是,是否要返回原来的 last_modified HTTP 头部,因为我们已经修改了文件内容,如果是 on 的话,就会继续返回原来的头部。

  • sub_filter_once on | off

    sub_filter_once 的意思是,是否只替换一次,默认打开,如果设置为 off 的话,那就会将响应中的内容全部扫描一遍并替换。

  • sub_filter_types mime-type

    这个指令是说针对那些文件类型进行替换,这里可以设置成 *,但是效率就会比较低了,需要根据实际情况考虑。

实战

配置文件如下:

server {
server_name sub.ziyang.com;
error_log logs/myerror.log info; location / {
sub_filter 'Nginx.oRg' '$host/nginx';
sub_filter 'nginX.cOm' '$host/nginx';
#sub_filter_once on;
sub_filter_once off;
#sub_filter_last_modified off;
sub_filter_last_modified on;
}
}

这里需要重新编译 Nginx,我这里把下一节需要的模块也一起编译进去了:

./configure --prefix=/Users/mtdp/myproject/nginx/test_nginx --with-http_sub_module --with-http_addition_module --with-http_realip_module
make
cp nginx ../../test_nginx/sbin/ # 复制编译好的 nginx 到之前的目录

执行热部署:

热部署的流程详见 Nginx 入门及命令行操作

kill -USR2 87693 # 使用新的 Nginx 二进制文件提供服务
kill -WINCH 87693 # 退出老的 Nginx 的 worker 进程
kill -quit 87693 # 优雅的退出老的 master 进程

在浏览器中打开 sub.ziyang.com:

这里面会发现,nginx.org 已经替换成了 sub.ziyang.com/nginx,nginx.com 也替换成了 sub.ziyang.com/nginx。

addition 模块

下面再来看一个过滤模块,addition 模块,它可以在响应的前后添加内容。

  • 功能:在相应前或者响应后增加内容,增加内容的方式,是通过新增子请求,根据子请求的响应来完成。

  • 模块:ngx_http_addition_filter_module

    默认未编译进 Nginx,通过 --with-http_addition_module 启用

指令

Syntax: add_before_body uri;
Default: —
Context: http, server, location Syntax: add_after_body uri;
Default: —
Context: http, server, location Syntax: addition_types mime-type ...;
Default: addition_types text/html;
Context: http, server, location

这里的三个指令都比较简单,说一下 add_before_bodyadd_after_body 后面的 uri,这个的意思是说,向指定 uri 发起子请求,根据子请求的响应来添加内容。

addition_types 指令是指定要添加的文件类型。

实战

配置文件如下:

server {
server_name addition.ziyang.com;
error_log logs/myerror.log info; location / {
#add_before_body /before_action;
#add_after_body /after_action;
#addition_types *;
}
location /before_action {
return 200 'new content before\n';
}
location /after_action {
return 200 'new content after\n';
}
location /testhost {
uninitialized_variable_warn on;
set $foo 'testhost';
return 200 '$gzip_ratio\n';
}
}

先看在注释掉 addition 模块的指令的情况下,会是什么效果:

➜  ~ curl addition.ziyang.com/a.txt
a

然后打开注释:

➜  ~ curl addition.ziyang.com/a.txt
new content before
a
new content after

在原响应前后都增加了内容。

这里面需要注意一点,在实际情况下,add_before_bodyadd_after_body 后面是其他的 uri,我这里为了简化,直接转发到对应的 location。

本文涉及到的所有配置文件我已经放在了 Nginx 配置文件,大家可以自取。


本文首发于我的个人博客:iziyang.github.io

Nginx 的过滤模块是干啥用的?的更多相关文章

  1. Nginx:HTTP过滤模块

    参考资料<深入理解Nginx> HTTP过滤模块也是一种HTTP模块,与普通HTTP处理模块不同在于: 1.一个请求仅由一个HTTP处理模块处理,而可以被任意个HTTP过滤模块处理 2.普 ...

  2. Nginx Http 过滤模块

    L69 执行顺序在content阶段后 log阶段前调用的 也就是处理完用户业务后 准备记录处理日志之前 我们可以到nginx http_model.c里查看 数组 执行顺序从下至上顺序执行 copy ...

  3. 《深入理解Nginx》阅读与实践(四):简单的HTTP过滤模块

    一.Nginx的HTTP过滤模块特征 一个请求可以被任意个HTTP模块处理: 在普通HTTP模块处理请求完毕并调用ngx_http_send_header()发送HTTP头部或调用ngx_http_o ...

  4. 简单的HTTP过滤模块

    简单的HTTP过滤模块 一.Nginx的HTTP过滤模块特征 一个请求可以被任意个HTTP模块处理: 在普通HTTP模块处理请求完毕并调用ngx_http_send_header()发送HTTP头部或 ...

  5. nginx图片过滤处理模块http_image_filter_module

    nginx图片过滤处理模块http_image_filter_module安装配置笔记 http_image_filter_module是nginx提供的集成图片处理模块,支持nginx-0.7.54 ...

  6. Nginx HttpSubModule sub_filter模块的过滤功能

    Nginx HttpSubModule sub_filter模块的过滤功能 发表于2年前(2013-08-05 10:39)   阅读(1481) | 评论(0) 0人收藏此文章, 我要收藏 赞0 5 ...

  7. 【Nginx】开发一个HTTP过滤模块

    与HTTP处理模块不同.HTTP过滤模块的工作是对发送给用户的HTTP响应做一些加工. server返回的一个响应能够被随意多个HTTP过滤模块以流水线的方式依次处理.HTTP响应分为头部和包体,ng ...

  8. Nginx之HTTP过滤模块

    1. HTTP 过滤模块 ngx_http_not_modified_module 仅对 HTTP 头部做处理.在返回 200 成功时,根据请求中 If-Modified-Since 或者 If-Un ...

  9. nginx日志模块与HTTP过滤模块与sub模块修改返回内容

    日志格式使用指令 指令介绍 Syntax: log_format name [escape=default|json|none] string ...; Default: log_format com ...

随机推荐

  1. python(安装)

    1.下载安装包 https://www.python.org/downloads/ 2.安装 默认安装路径:C:\python3(建议自定义安装路径) 3.配置环境变量 [右键计算机]-->[属 ...

  2. python文件路径分隔符的详细分析

    写了挺久的python,文件分隔符的掌握肯定是必须的,但是我之前写的都是不规范的文件路径分隔符,例如‘’C:\User\temp\python.txt’,一直都没有报过错.也不知为啥,今天查阅资料才知 ...

  3. AWS bind: cannot assign requested address

    最近在AWS上安装Redis,遇到一个坑. Redis默认配置文件中有个bind配置项,默认为127.0.0.1.此时只能在服务器内部访问Redis. 为了从服务器外部访问Redis,我给bind添加 ...

  4. JavaScript键值对集合怎么使用

    JavaScript键值对集合怎么使用 我们可以对此键值对集合分为3种难度 1.简单的使用 var arr = { 'cn': "中国", 'usa': '美国', 'jp': ' ...

  5. SPFA+链式前向星

    板子 #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll inf=2<<3 ...

  6. K - Painful Bases 状压dp

    Painful Bases LightOJ - 1021 这个题目一开始看,感觉有点像数位dp,但是因为是最多有16进制,因为限制了每一个数字都不同最多就有16个数. 所以可以用状压dp,看网上题解是 ...

  7. 单元测试中使用Spring的ReflectionTestUtils更方便

    1 简介 ReflectionUtils是Spring中一个常用的类,属于spring-core包:ReflectionTestUtils则属于spring-test包.两者功能有重叠的地方,而Ref ...

  8. 李婷华 201771010113 《面向对象程序设计(java)》第一周学习总结

    第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.com 薄荷蓝莓 程序设计评测:https://pintia.cn/ 1957877441@q ...

  9. 移动端H5支付(微信和支付宝)

    我们直接进入主题吧,先说功能: 1.用户通过我们的页面输入充值帐号和金额调起支付(微信或者支付宝),支付成功返回获取支付结果. 2.微信支付成功后重定向到指定页面(没有设置重定向地址的话,默认返回调起 ...

  10. Keycloak & Asp.net core webapi 整合跳坑之旅

    前言 之前,一直使用IdentityServer4作为.net core程序的外部身份认证程序,ID4的优点自不必说了,缺点就是缺乏完善的管理界面. 后来,学习java quarkus框架时,偶然遇到 ...