Nginx学习(7)—— 过滤模块(filter)

2023-05-16

文章目录

  • 过滤模块简介
    • 执行时间和内容
    • 执行顺序
      • Nginx是怎么按照次序依次来执行各个过滤模块的呢
      • 这些过滤模块的简述(按执行顺序)
  • 模块编译
  • 过滤模块分析
    • 相关结构体
  • 响应头过滤函数
  • 响应体过滤函数
    • 主要功能介绍
    • 发出子请求
    • 优化措施

过滤模块简介

执行时间和内容

  • 过滤模块是过滤响应头和内容的模块。它工作在获取回复内容之后,向用户发送响应之前。它的处理过程分为两个阶段,过滤HTTP回复的头部和主体,在这两个阶段可以分别对头部和主体进行修改。

  • src/http/ngx_http.c中有对filter函数指针变量的定义:
    所有模块的响应内容都要调用这两个函数指针指向的函数,被这两个函数处理后再返回给客户端。

    • ngx_http_output_header_filter_pt ngx_http_top_header_filter;
    • ngx_http_output_body_filter_pt ngx_http_top_body_filter;

执行顺序

  • filter的调用顺序在编译的时候就决定了,在auto/modules文件中有对其控制编译的脚本。
  • 当编译完成后在objs/目录下的ngx_modules.c文件中有一个ngx_module_t类型的数组ngx_modules,里面记录着nginx所有使用到的模块:我们只关心filter模块
    在这里插入图片描述
  • 从write_filter到not_modified_filter,模块的执行顺序是反向的。也就是说最早执行的是not_modified_filter,然后各个模块依次执行。
  • 所有第三方的模块只能加入到copy_filter和headers_filter模块之间执行。

Nginx是怎么按照次序依次来执行各个过滤模块的呢

通过局部的全局变量,比如,在每个filter模块,会有类似如下代码:

static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;

ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_example_header_filter;
ngx_http_next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_example_body_filter;
  • ngx_http_top_header_filter是一个全局变量。当编译进一个filter模块的时候,就被赋值为当前filter模块的处理函数。
  • 而ngx_http_next_header_filter是一个局部全局变量,它保存了编译前上一个filter模块的处理函数。所以整体看来,就像用全局变量组成的一条单向链表。
  • 每个模块想执行下一个过滤函数,只要调用一下ngx_http_next_header_filter这个局部变量。而整个过滤模块链的入口,需要调用ngx_http_top_header_filter这个全局变量。ngx_http_top_body_filter的行为与header fitler类似。

这些过滤模块的简述(按执行顺序)

filter模块描述
ngx_http_not_modified_filter_module默认打开,如果请求的if-modified-since等于回复的last-modified间值,说明回复没有变化,清空所有回复的内容,返回304
ngx_http_range_body_filter_module默认打开,只是响应体过滤函数,支持range功能,如果请求包含range请求,那就只发送range请求的一段内容
ngx_http_copy_filter_module始终打开,只是响应体过滤函数, 主要工作是把文件中内容读到内存中,以便进行处理
ngx_http_headers_filter_module始终打开,可以设置expire和Cache-control头,可以添加任意名称的头
ngx_http_userid_filter_module默认关闭,可以添加统计用来识别用户的cookie
ngx_http_charset_filter_module默认关闭,可以添加charset,也可以将内容从一种字符集转换到另外一种字符集,不支持多字节字符集
ngx_http_ssi_filter_module默认关闭,过滤SSI请求,可以发起子请求,去获取include进来的文件
ngx_http_postpone_filter_module始终打开,用来将子请求和主请求的输出链合并
ngx_http_gzip_filter_module默认关闭,支持流式的压缩内容
ngx_http_range_header_filter_module默认打开,只是响应头过滤函数,用来解析range头,并产生range响应的头
ngx_http_chunked_filter_module默认打开,对于HTTP/1.1和缺少content-length的回复自动打开
ngx_http_header_filter_module始终打开,用来将所有header组成一个完整的HTTP头
ngx_http_write_filter_module始终打开,将输出链拷贝到r->out中,然后输出内容

模块编译

Nginx可以方便的加入第三方的过滤模块。在过滤模块的目录里,首先需要加入config文件,文件的内容如下:

ngx_addon_name=ngx_http_example_filter_module
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_example_filter_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_example_filter_module.c"

说明把这个名为ngx_http_example_filter_module的过滤模块加入,ngx_http_example_filter_module.c是该模块的源代码。

过滤模块分析

相关结构体

  • 单向链表: ngx_chain_t

    typedef struct ngx_chain_s           ngx_chain_t;
    struct ngx_chain_s {
        ngx_buf_t    *buf;
        ngx_chain_t  *next;
    };
    

    在过滤模块中,所有输出的内容都是通过一条单向链表所组成。这种单向链表的设计,正好应和了Nginx流式的输出模式。每次Nginx都是读到一部分的内容,就放到链表,然后输出出去。这种设计的好处是简单,非阻塞,但是相应的问题就是跨链表的内容操作非常麻烦,如果需要跨链表,很多时候都只能缓存链表的内容。

  • 单链表负载的就是ngx_buf_t结构体

    typedef struct ngx_buf_s  ngx_buf_t;
    struct ngx_buf_s {
        u_char          *pos;		/* 当前buffer真实内容的起始位置 */
        u_char          *last;		/* 当前buffer真实内容的结束位置 */
        off_t            file_pos;	/* 在文件中真实内容的起始位置 */
        off_t            file_last;	 /* 在文件中真实内容的结束位置 */
    
        u_char          *start;		/* buffer内存的开始分配的位置 */
        u_char          *end;		/* buffer内存的结束分配的位置 */
        ngx_buf_tag_t    tag;		/* buffer属于哪个模块的标志 */
        ngx_file_t      *file;		/* buffer所引用的文件 */
        ngx_buf_t       *shadow;	/* 用来引用替换过后的buffer,以便当所有buffer输出以后,这个影子buffer可以被释放。*/
        
        /* the buf's content could be changed */
        unsigned         temporary:1;
    
        /*
         * the buf's content is in a memory cache or in a read only memory
         * and must not be changed
         */
        unsigned         memory:1;
    
        /* the buf's content is mmap()ed and must not be changed */
        unsigned         mmap:1;
    
        unsigned         recycled:1;	/* 内存可以被输出并回收 */
        unsigned         in_file:1;		/* buffer的内容在文件中 */
        unsigned         flush:1;/* 马上全部输出buffer的内容, gzip模块里面用得比较多 */
        unsigned         sync:1;/* 基本上是一段输出链的最后一个buffer带的标志,标示可以输出,
        							有些零长度的buffer也可以置该标志*/
        unsigned         last_buf:1;	/* 所有请求里面最后一块buffer,包含子请求 */
        unsigned         last_in_chain:1;	/* 当前请求输出链的最后一块buffer */
    
        unsigned         last_shadow:1;	/* shadow链里面的最后buffer,可以释放buffer了 */
        unsigned         temp_file:1;	/* 是否是暂存文件 */
    
        /* STUB */ int   num;	/* 统计用,表示使用次数 */
    };
    

    一般buffer结构体可以表示一块内存,内存的起始和结束地址分别用start和end表示,pos和last表示实际的内容。如果内容已经处理过了,pos的位置就可以往后移动。如果读取到新的内容,last的位置就会往后移动。所以buffer可以在多次调用过程中使用。如果last等于end,就说明这块内存已经用完了。如果pos等于last,说明内存已经处理完了。

响应头过滤函数

  • 响应头过滤函数主要的用处就是处理HTTP响应的头,可以根据实际情况对于响应头进行修改或者添加删除。响应头过滤函数先于响应体过滤函数,而且只调用一次,所以一般可作过滤模块的初始化工作。

响应头过滤函数的入口只有一个:

ngx_int_t
ngx_http_send_header(ngx_http_request_t *r)
{
    ···
    return ngx_http_top_header_filter(r);
}

该函数向客户端发送回复的时候调用,然后按上述的执行顺序。该函数的返回值一般是NGX_OK,NGX_ERROR和NGX_AGAIN,分别表示处理成功,失败和未完成。
可以把HTTP响应头的存储方式想象成一个hash表,在Nginx内部可以查找和修改各个响应头,ngx_http_header_filter_module过滤模块把所有的HTTP头组合成一个完整的buffer,最终ngx_http_write_filter_module过滤模块把buffer输出。

响应体过滤函数

  • 响应体过滤函数是过滤响应主体的函数。ngx_http_top_body_filter这个函数每个请求可能会被执行多次,它的入口函数是ngx_http_output_filter

入口函数代码如下

ngx_int_t
ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
    ngx_int_t          rc;
    ngx_connection_t  *c;

    c = r->connection;

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   "http output filter \"%V?%V\"", &r->uri, &r->args);

    rc = ngx_http_top_body_filter(r, in);

    if (rc == NGX_ERROR) {
        /* NGX_ERROR may be returned by any filter */
        c->error = 1;
    }

    return rc;
}

ngx_http_output_filter可以被一般的静态处理模块调用,也可能在upstream模块里面被调用,对于整个请求的处理阶段来说,他们的用处都是一样的,就是把响应内容过滤,然后发给客户端。

具体模块的响应体过滤函数的格式类似这样

static int
ngx_http_example_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
	···
	return ngx_http_next_body_filter(r, in);
}

该函数的返回值一般是NGX_OK,NGX_ERROR和NGX_AGAIN,分别表示处理成功,失败和未完成。

主要功能介绍

  • 响应的主体内容就存于单链表in,链表一般不会太长,有时in参数可能为NULL。in中存有buf结构体中,对于静态文件,这个buf大小默认是32K;对于反向代理的应用,这个buf可能是4k或者8k。为了保持内存的低消耗,Nginx一般不会分配过大的内存,处理的原则是收到一定的数据,就发送出去。一个简单的例子,可以看看Nginx的chunked_filter模块,在没有contentlengt的情况下,chunk模块可以流式(stream)的加上长度,方便浏览器接收和显示内容。

  • 在响应体过滤模块中,尤其要注意的是buf的标志位,完整描述可以在“相关结构体”这个节中看到。如果buf中包含last标志,
    说明是最后一块buf,可以直接输出并结束请求了。如果有flush标志,说明这块buf需要马上输出,不能缓存。如果整块
    buffer经过处理完以后,没有数据了,你可以把buffer的sync标志置上,表示只是同步的用处。

  • 当所有的过滤模块都处理完毕时,在最后的write_fitler模块中,Nginx会将in输出链拷贝到r->out输出链的末尾,然后调用sendfile或者writev接口输出。由于Nginx是非阻塞的socket接口,写操作并不一定会成功,可能会有部分数据还残存在r->out。在下次的调用中,Nginx会继续尝试发送,直至成功。

发出子请求

  • Nginx过滤模块一大特色就是可以发出子请求,也就是在过滤响应内容的时候,你可以发送新的请求,Nginx会根据你调用的
    先后顺序,将多个回复的内容拼接成正常的响应主体。一个简单的例子可以参考addition模块。
  • Nginx是如何保证父请求和子请求的顺序呢? 当Nginx发出子请求时,就会调用ngx_http_subrequest函数,将子请求插入父请求的r->postponed链表中。子请求会在主请求执行完毕时获得依次调用。子请求同样会有一个请求所有的生存期和处理过程,也会进入过滤模块流程。
  • 关键点是在postpone_filter模块中,它会拼接主请求和子请求的响应内容。r->postponed按次序保存有父请求和子请求,它是一个链表,如果前面一个请求未完成,那后一个请求内容就不会输出。当前一个请求完成时并输出时,后一个请求才可输出,当所有的子请求都完成时,所有的响应内容也就输出完毕了。

优化措施

  • Nginx过滤模块涉及到的结构体,主要就是chain和buf,非常简单。在日常的过滤模块中,这两类结构使用非常频繁,Nginx采用类似freelist重复利用的原则,将使用完毕的chain或者buf结构体,放置到一个固定的空闲链表里,以待下次使用。
  • 比如,在通用内存池结构体中,pool->chain变量里面就保存着释放的chain。而一般的buf结构体,没有模块间公用的空闲链表池,都是保存在各模块的缓存空闲链表池里面。对于buf结构体,还有一种busy链表,表示该链表中的buf都处于输出状态,如果buf输出完毕,这些buf就可以释放并重复利用了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Nginx学习(7)—— 过滤模块(filter) 的相关文章

  • 您是否正在尝试将目录挂载到文件上(或反之亦然)?

    我有一个带有版本的docker17 06 0 ce 当我尝试使用 docker 和命令安装 NGINX 时 docker run p 80 80 p 8080 8080 name nginx v PWD www www v PWD conf
  • 使用嵌套数组过滤对象数组

    所以我试图在对象数组上设置嵌套过滤器 问题是过滤器应用在对象内部的另一个对象数组的键上 这是代码 const items name 123 id 1 value true arr id 1 name 456 id 2 value false
  • Websocket-rails 不适用于 Nginx 和 Unicorn 的生产环境

    我有 Rails 3 2 应用程序和 gem websocket rails 0 7 在开发机器上 一切正常 在生产环境中 我使用 Nginx 1 6 作为代理服务器 使用 Unicorn 作为 http 服务器 Thin 用于独立模式 如
  • Solr距离过滤

    我正在尝试使用 Solr 进行距离范围搜索 我知道在5公里范围内进行搜索过滤很容易 q fq geofilt pt 45 15 93 85 sfield store d 5 我所追求的是如果我正在寻找一系列的说法 如何做同样的事情5至10公
  • C 中带有通配符的目录列表

    有现成的功能吗C可以使用列出目录的内容wildcards过滤掉文件名 例如 相当于 echo b 它显示四个字符长且不以 b 开头的目录条目的名称 我知道我可以使用scandir 但是 我需要提供自己的过滤功能 include
  • 如何在 nginx.conf 中引用操作系统环境变量

    在 nginx conf 中 设置变量后set name value 我可以像这样参考它 name 但是当我导出操作系统环境变量时 经过env name from env like https nginx org en docs ngx c
  • 使用 nginx 代理时在 RStudio 中运行闪亮的应用程序

    我正在尝试使用通过 nginx 代理的 RStudio 服务器来开发一个闪亮的应用程序 当我使用 RStudio 而不是服务器 来运行闪亮的应用程序时 一切正常 但是 当我通过代理 RStudio 运行时 该应用程序出现在 查看器 窗格中
  • 为什么 Nginx 以相反的顺序提供客户端 SSL DN?

    我很好奇为什么某些 Web 服务器 例如 Nginx 以相反的顺序提供客户端 SSL DN Web 应用程序将 DN 发布到 Java Web 服务 该服务尝试创建 Javajavax naming ldap LdapName http d
  • 为从 nginx 反向代理转发的请求添加唯一 id

    我们运行 nginx 作为反向代理 将请求转发到运行 Compojure 的 Clojure 应用程序 Compojure 是一个封装 Jetty 的库 为我们的应用程序提供服务 Web 请求的能力 目前 我们捕获 nginx 和 Cloj
  • 同时使用两个数组中的元素的过滤器

    假设我们有两个大小相同的数组 A and B 现在 我们需要一个过滤器 对于给定的掩码大小 从以下位置选择元素A 但删除掩码的中心元素 并在其中插入相应的元素B 所以 3x3 伪掩码 看起来类似于 A A A A B A A A A 对平均
  • 如何根据开始和结束条件过滤数据?

    我试图根据依赖于连续日期的两个条件来过滤数据 我在寻找对于 5 个以上的连续日期 值低于 2 with a 缓冲期 of 值 2 到 5 最多连续 3 天 它看起来像这样 很抱歉这里的 Excel 尝试很糟糕 第 1 天到第 10 天将包括
  • nginx 将虚拟目录重写为文件

    这应该很容易做到 但我的头撞在墙上了 如果我收到对 www mysite com mypath 的请求 我想提供 www mysite com myotherpath thisfile html 的内容 我如何使用 nginx 配置来做到这
  • Nginx反向代理(proxy_pass)不传递子文件夹

    我想在子文件夹配置中运行应用程序 Mattermost 例如 https www example com mattermost https www example com mattermost location mattermost gzi
  • 如何在java中的组合框之间使用过滤器?

    我的数据库中有两个表 分别是学期表和课程表 学期表中有学期 ID 课程 ID 课程名称和 Sdepartment 部门名称 课程表有课程 ID 和课程名称 我的 jframe 有两个组合框 第一个用于选择部门 第二个用于选择课程 我想选择所
  • `uwsgi_modifier1 30` 指令没有按照记录从 PATH_INFO 中删除 SCRIPT_NAME

    这是我的 nginx 虚拟主机配置 debian cat etc nginx sites enabled mybox server listen 8080 root www index index html index htm server
  • Nginx 正在向 uWSGI 发出非常旧的请求?

    我看到一种奇怪的情况 Nginx 或 uwsgi 似乎正在建立一个很长的传入请求队列 并在客户端连接超时后很长时间内尝试处理它们 我想理解并停止这种行为 以下是更多信息 My Setup 我的服务器使用 Nginx 通过 Unix 文件套接
  • Nginx 背后的多个 Meteor 站点

    这个问题与this https stackoverflow com questions 10936242 how can i correct the meteor base url in a nginx reverse proxy conf
  • 我怎样才能重写这个nginx“if”语句?

    例如 我想这样做 if http user agent MSIE 6 0 http user agent MSIE 7 0 etc etc rewrite ROOT ROOT ancient last break 而不是这个 if http
  • HttpResponse 过滤器不返回任何内容

    我编写了一个 HttpModule 用于拦截对 WebResource axd 处理程序的调用 以便我可以对 javascript 执行一些后处理 该模块包装 Response Filter 流以执行其处理并将其更改写入底层流 我遇到的问题
  • 将 dataGridView 绑定到绑定列表并按文本框过滤行

    我正在开发一个 Winforms 应用程序 并且有一个已经绑定到 dataGridView 的对象的 BindingList 我还有一个 过滤器 文本框 如果它们与文本框文本不匹配 我想从 datagridview 行中过滤掉行 我想以某种

随机推荐

  • VideoJS 网页直播实现默认静音

    在开发 LiveQing高性能流媒体服务器 网页直播多分屏的时候 产品提出议建说 能不能在多分屏的时候 默认静音状态 因为多分屏界面 如果声音打开 好多个直播画面同时发出声音太过嘈杂 体验不好 我表示赞同 心想 这个应该不难处理吧 结果踩到
  • VideoJS 网页直播实现双击全屏

    最近接到客户需求 要求我们的网页直播播放器更加符合广大人民群众的使用习惯 实现双击全屏的效果 目前网页直播播放器使用了开源的 VideoJS 它的默认效果是单击播放区域暂停 只能通过右下角的最大化按钮触发最大化 要实现双击全屏播放的效果 就
  • LivePlayer H5直播/点播播放器安装与使用

    LivePlayer H5播放器 简介 H5直播 点播播放器 xff0c 使用简单 xff0c 功能强大 xff0c 免费使用 支持m3u8播放 支持HTTP FLV播放 支持RTMP播放 支持直播和点播播放 支持播放器快照截图 支持点播多
  • Echarts 修改折线的颜色和折线的点的大小方法

    在做SPC分析的时候或者一些专业的分析的时候有的客户会要求 点的大小 样式等 具体的设置方法如下 series type 39 line 39 showSymbol true symbol 39 circle 39 设定为实心点 symbo
  • 抽象工厂模式

    抽象工厂模式针对的是对产品族 xff0c 而不是产品等级结构 产品族 xff1a 同一厂商生产的产品 产品等级 xff1a 同一产品 xff0c 不同厂商的产品 比如水果类里面由苹果和香蕉 xff0c 水果就是产品族 xff0c 苹果香蕉就
  • 面向对象单例模式

    单例模式 xff1a 一个类只能创建一个对象 span class token keyword class span span class token class name A span span class token punctuati
  • 设计模式之代理模式

    概念 xff1a 为其他对象提供一种代理 xff0c 用来控制对象的访问 在某些情况下 xff0c 一个对象不适合或不能直接引用另一个对象 xff0c 而代理对象可以在客户端和目标对象之间起到中介作用 span class token co
  • ARM接口技术基础

    ARM介绍 嵌入式系统 xff1a 嵌入式系统 61 嵌入式硬件 43 嵌入式软件 硬件是软件的载体 xff0c 软件是硬件的灵魂 嵌入式软件 xff1a 1 裸机 xff1a APP 2 系统 xff1a OS 43 APP 嵌入式硬件
  • ARM指令之MOV指令汇编与机器码的对应关系

    指令条件码 条件码就是一种简单的测试ALU状态标志位的方法 mov指令机器码 比如 xff1a mov r1 3 立即数 xff1a 3 第一个操作数 xff1a 寄存器1 S xff1a 0 xff08 注意 xff1a mov指令后面加
  • 设计模式之外观模式

    什么是外观模式 外观模式就是将一个复杂的子类系统抽象到同一个接口进行管理 外界只需要通过此接口与子类系统进行交互 xff0c 不需要直接与复杂的子类系统进行交互 外观模式属于结构型模式 外观模式案例 1 实现KTV模式 xff1a 打开电视
  • 设计模式之适配器模式

    概念 将一个类的接口转换成客户希望的另外一个接口 使得原本由于接口不兼容而不能一起工作的那些类可以一起工作 用vector容器中的for each 举例子 span class token keyword class span span c
  • Qt基础学习笔记

    Qt中的常用快捷键 注释 xff1a ctrl 43 运行 xff1a ctrl 43 r 编译 xff1a ctrl 43 b 帮助文档 xff1a F1 自动对齐 xff1a ctrl 43 i 同名之间 h文件与 cpp文件的切换 x
  • Nginx学习 (1) —— 初识Nginx(编译安装、启动停止、简单配置)

    文章目录 Nginx的发行版本Nginx的编译安装 xff08 ubuntu18 04 xff09 Nginx相关操作Nginx启动停止命令安装Nginx为系统服务 Nginx的目录结构与基本原理目录结构 xff1a 基本运行原理 xff1
  • Nginx学习 (2) —— 虚拟主机配置

    文章目录 虚拟主机原理域名解析与泛域名解析 xff08 实践 xff09 配置文件中ServerName的匹配规则技术架构多用户二级域名短网址 虚拟主机原理 为什么需要虚拟主机 xff1a 当一台主机充当服务器给用户提供资源的时候 xff0
  • 如任让Echarts默认显示全部的数据(x轴(时间轴)默认显示查询到的所有数据)

    Echarts绘制折线图 有时候会用到时间轴 但是有时候时间轴默认显示的是部分数据 而不是全部的数据 当客户要求默认显示全部的数据的时候 就可以使用下面的方法 把dataZoom属性的startValue设置为0即可 dataZoom st
  • Nginx学习(3)—— 反向代理、负载均衡、动静分离、URLRewrite、防盗链

    文章目录 网关 代理与反向代理Nginx的反向代理配置基于反向代理的负载均衡的配置负载均衡策略负载均衡权重相关配置 xff08 weight xff09 动静分离Nginx配置动静分离 URL rewrite伪静态配置负载均衡 43 URL
  • Nginx学习(4)—— 高可用配置(keepalived实现Nginx的高可用)

    文章目录 高可用场景及解决方案keepalived的安装 高可用场景及解决方案 一般高可用的服务端会都有备用服务 xff0c 当某一个服务节点挂掉的时候就会有备用机顶上 这往往需要反向代理 Nginx 来将连接切换到可用的服务机器上 如下图
  • Nginx学习(5)—— 基本结构(源码)

    文章目录 Nginx源码学习基本数据结构1 字符串结构 xff1a ngx str t2 类似资源管理的结构 xff1a ngx pool t3 Nginx数组结构 xff1a ngx array t4 哈希表结构 xff1a 1 ngx
  • Nginx学习(6)—— handler模块(自定义handler配置模块的编码编译)

    文章目录 Nginx请求的处理handler简介handler模块的基本结构模块配置结构模块配置指令先看一下 ngx command t 结构 一个模块配置的demo简单模块配置的案例演示 模块上下文结构模块的定义handler模块的基本结
  • Nginx学习(7)—— 过滤模块(filter)

    文章目录 过滤模块简介执行时间和内容执行顺序Nginx是怎么按照次序依次来执行各个过滤模块的呢这些过滤模块的简述 xff08 按执行顺序 xff09 模块编译过滤模块分析相关结构体 响应头过滤函数响应体过滤函数主要功能介绍发出子请求优化措施