`
奔跑的羚羊
  • 浏览: 576833 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

nginx模块开发入门(九) -4 Filters

 
阅读更多
4. Filters
  
    注:本节事例http/modules/ngx_http_chunked_filter_module.c

    Filter操作handler生成的响应。头部filter操作HTTP头,body filter操作响应的内容。

4.1. 剖析Header Filter
Anatomy of a Header Filter



    Header Filter由三个步骤组成:

   1. 决定何时操作响应
   2. 操作响应
   3. 调用下一个filter

    举个例子,比如有一个简化版本的"not modified" header filter:如果客户请求头中的If- Modified-Since和响应头中的Last-Modified相符,它把响应状态设置成304。注意这个头部filter只读入一个参数:ngx_http_request_t结构体,而我们可以通过它操作到客户请求header和一会将被发送的响应response header。
static
ngx_int_t ngx_http_not_modified_header_filter(ngx_http_request_t *r)
{
    time_t  if_modified_since;

    if_modified_since = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
                              r->headers_in.if_modified_since->value.len);

/* step 1: decide whether to operate */
    if (if_modified_since != NGX_ERROR && 
        if_modified_since == r->headers_out.last_modified_time) {

/* step 2: operate on the header */
        r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
        r->headers_out.content_type.len = 0;
        ngx_http_clear_content_length(r);
        ngx_http_clear_accept_ranges(r);
    }

/* step 3: call the next filter */
    return ngx_http_next_header_filter(r);
}

结构headers_out和我们在hander那一节中看到的是一样的(参考http/ngx_http_request.h),也可以随意处置。

4.2. 剖析Body Filter
Anatomy of a Body Filter


    因为body filter一次只能操作一个buffer chain(链表),这使得编写body filter需要一定的技巧。模块需要知道什么时候可以覆盖输入buffer,用新申请的buffer替换已有的,或者在现有的某个buffer前或后插入一个新buffer。有时候模块会收到许多buffer使得它不得不操作一个不完整的链表,这使得事情变得更加复杂了。而更加不幸的是,Nginx没有为我们提供上层的API来操作buffer链表,所以body filter是比较难懂(当然也比较难写)。但是,有些操作你还是可以看出来的。


    一个body filter原型大概是这个样子(例子代码从Nginx源代码的“chunked” filter中取得):
static ngx_int_t ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in);


    第一个参数是我们的老朋友"请求结构体"(ngx_http_request_t) ,第二个参数则是指向当前部分链表(chain)表头的指针(可能包含0,1,或更多的buffer)。

    再来举个例子好了。假设我们想要做的是在每个请求之后插入文本"<l!-- Served by Nginx -->"。首先,我们需要判断给我们的buffer链表中是否已经包含响应的最终buffer。就像之前我说的,这里没有简便好用的API,所以我们只能自己来写个循环:
    ngx_chain_t *chain_link;
    int chain_contains_last_buffer = 0;

    chain_link = in;
    for ( ; ; ) {
        if (chain_link->buf->last_buf)
            chain_contains_last_buffer = 1;
        if (chain_link->next == NULL)
            break;
        chain_link = chain_link->next;
    }



     如果我们没有最后的缓冲区,就返回:
    if (!chain_contains_last_buffer)
        return ngx_http_next_body_filter(r, in);


     很好,现在最后一个缓冲区已经存在链表中了。接下来我们分配一个新缓冲区:
    ngx_buf_t    *b;
    b = ngx_calloc_buf(r->pool);
    if (b == NULL) {
        return NGX_ERROR;
    }


     把数据放进去:
    b->pos = (u_char *) "<!-- Served by Nginx -->";
    b->last = b->pos + sizeof("<!-- Served by Nginx -->") - 1;


     把这个缓冲区挂在新的链表上:
    ngx_chain_t   *added_link;

    added_link = ngx_alloc_chain_link(r->pool);
    if (added_link == NULL)
        return NGX_ERROR;

    added_link->buf = b;
    added_link->next = NULL;

 
     最后,把这个新链表挂在先前链表的末尾:
    chain_link->next = added_link;


     并根据变化重置变量"last_buf"的值:
    chain_link->buf->last_buf = 0;
    added_link->buf->last_buf = 1;


     再将修改过的链表传递给下一个输出过滤函数:
return ngx_http_next_body_filter(r, in);


     现有的函数做了比我们更多的工作,比如mod_perl($response->body =~ s/$/<!-- Served by mod_perl -->/),但是缓冲区链确实是一个强大的构想,它可以让程序员渐进地处理数据,这使得客户端可以尽可能早地得到响应。但是依我来看,缓冲区链表实在需要一个更为干净的接口,这样程序员也可以避免操作不一致状态的链表。但是目前为止,所有的操作风险都得自己控制。

4.3. Filter的装载
Filter Installation


      Filter在回调函数post-configuration中被装载。header filter和body filter都是在这里被装载的。

      我们以chunked filter模块为例来具体看看:
static ngx_http_module_t  ngx_http_chunked_filter_module_ctx = {
    NULL,                                  /* preconfiguration */
    ngx_http_chunked_filter_init,          /* postconfiguration */
  ...
};


      ngx_http_chunked_filter_init中的具体实现如下:
static ngx_int_t
ngx_http_chunked_filter_init(ngx_conf_t *cf)
{
    ngx_http_next_header_filter = ngx_http_top_header_filter;
    ngx_http_top_header_filter = ngx_http_chunked_header_filter;

    ngx_http_next_body_filter = ngx_http_top_body_filter;
    ngx_http_top_body_filter = ngx_http_chunked_body_filter;

    return NGX_OK;
}

    发生了什么呢?好吧,如果你还记得,过滤模块组成了一条”接力链表“(CHAIN OF RESPONSIBILITY)。当handler生成一个响应后,调用2个函数:ngx_http_output_filter它调用全局函数ngx_http_top_body_filter
以及ngx_http_send_header 它调用全局函数ngx_top_header_filter

    ngx_http_top_body_filterngx_http_top_header_filter是body和header各自的头部filter链的”链表头“。链表上的每一个”连接“都保存着链表中下一个连接的函数引用(分别是 ngx_http_next_body_filter ngx_http_next_header_filter)。当一个filter完成工作之后,它只需要调用下一个filter,直到一个特殊的被定义成”write“的filter被调用,这个”write“filter的作用是包装最终的HTTP响应。你在这个filter_init函数中看到的就是,模块把自己添加到filter链表中;它先把旧的”头部“filter当做是自己的”下一个“,然后再声明”它自己“是”头部“filter。(因此,最后一个被添加的filter会第一个被执行。)

引用
边注: 这到底是怎么工作的?
     每个filter要么返回一个错误码,要么用下面的作为返回语句

return ngx_http_next_body_filter();


     因此,如果filter顺利链执行到了链尾(那个特别定义的的”write“filter),将返回一个"OK"响应,但如果执行过程中遇到了错误,链将被砍断,同时Nginx将给出一个错误的信息。这是一个单向的,错误快速返回的,只使用函数引用实现的链表。帅啊!

分享到:
评论

相关推荐

    nginx + nginx-http-flv-module-1.2.9

    nginx-http-flv-module 是由 nginx 开发社区创建的一个第三方模块,用于在 Nginx 上实现 HTTP 直播(HTTP Live Streaming,HLS)和FLV格式的视频流。FLV(Flash Video)是 Adobe Flash 平台广泛使用的视频格式,...

    添加nginx-http-flv-module模块并重新编译后的nginx(windows版)

    4. 集成模块:进入Nginx的`src`目录,然后将`nginx-http-flv-module`目录复制或链接到`src`目录下。 5. 重新配置:运行`configure`脚本来配置Nginx,确保指定新添加的模块。命令可能类似于: ``` ./configure --...

    nginx带nginx-http-flv模块windows编译版rtmp

    Nginx-RTMP是Nginx的一个扩展模块,由Adobe Systems开发,用于支持Real-Time Messaging Protocol (RTMP)。RTMP是一种协议,常用于在线流媒体传输,如视频直播服务。Nginx-RTMP模块允许Nginx接收来自Flash Player或...

    nginx-sticky-module-1.25.zip

    nginx sticky是nginx的module,可以实现基于cookie的负载均衡。 下载后,在编译安装nginx时,用--add-module... ./configure --prefix=/usr/local/nginx-1.6.0 --add-module=../nginx-sticky-module-1.25 --without-...

    集成了nginx-http-flv-module 1.2.9模块的64位nginx-1.21.4程序

    `nginx-http-flv-module`是Nginx的一个第三方模块,由张洪君开发,用于处理FLV格式的流媒体数据。通过这个模块,Nginx可以支持RTMP协议,实现实时流媒体的推拉流,为Flash Player和其他支持RTMP的客户端提供服务。...

    win环境使用nginx的nginx-http-flv-module.zip

    在windows 7 64位 环境下使用nginx的nginx-http-flv-module搭建flv视频流播放所有的安装包,参考:https://blog.csdn.net/qq_33071429/article/details/102628008

    nginx-1.19.3_nginx-http-flv-module.rar

    标题中的"nginx-1.19.3_nginx-http-flv-module.rar"表明这是一个关于Nginx服务器的软件包,特别地,它包含了Nginx的1.19.3版本,并且已经集成了`nginx-http-flv-module`模块。这个模块是用于支持HTTP FLV(Flash ...

    nginx-rtmp模块源码包nginx-rtmp-module-master

    **Nginx-RTMP 模块详解** Nginx-RTMP 模块是 Nginx 的一个扩展,用于处理 Real-Time Messaging Protocol (RTMP) 流,它允许 Nginx 作为 RTMP 服务器运行,支持直播和点播服务。这个源码包 "nginx-rtmp-module-...

    nginx-http-flv-module(windows版)

    --&gt; nginx-1.21.6 ======================== 在网上查找半天都只有教程,没有可免费下载的版本,深知没有积分遍地找资源的痛苦,无奈之下只好自己按照教程一步一个坑编译出来的,供大家免费下载使用。(无毒放心使用...

    nginx上传下载之nginx-upload-module-2.3.0

    cp -r ../nginx-upload-module-2.3.0 nginx-1.21.x/ cd nginx-1.21.x/ ./configure --add-module=../nginx-upload-module-2.3.0 \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-pcre make ...

    windows下编译nginx-http-flv-moudle

    3. **nginx-http-flv-module**: 这是Nginx的一个第三方模块,由社区开发,用于支持HTTP FLV直播。它提供了处理RTMP流并将它们转化为适应HTTP的FLV流的能力,让客户端可以无插件播放。 4. **编译过程**: 在Windows上...

    windows平台nginx编译nginx-http-flv-module

    在给定的压缩包文件中,"使用必看.txt"可能包含了编译和使用过程中的注意事项,而"nginx-rtmp.zip"可能是包含了RTMP模块的源代码,这在搭建流媒体服务器时也会用到,因为HTTP FLV Module通常与RTMP模块结合使用,为...

    nginx-upstream-jvm-route-1.15

    【标题】"nginx-upstream-jvm-route-1.15" 涉及的核心知识点是Nginx的upstream模块与JVM路由的整合,特别针对Nginx 1.15版本。这个项目旨在解决在配置Nginx时遇到的特定错误提示“nginx: [emerg] invalid parameter ...

    nginx-goodies-nginx-sticky-module-ng-08a395c66e42.zip

    Sticky是nginx的一个模块,它是基于cookie的一种nginx的负载均衡解决方案,通过分发和识别cookie,来使同一个客户端的请求落在同一台服务器上,默认标识名为route (a)客户端首次发起访问请求,nginx接收后,发现...

    nginx-1.19.3-http-flv.zip

    1. 采用nginx最新版编译,包含最新的nginx-http-flv-module,以及基础模块openssl、prce、zlib 2. 整体打包,已配置好nginx.conf的http-flv直播流,以及http web环境。无需任何配置即可使用 3. 自带windows的服务...

    nginx-http-flv-module(nginx1.19.3&amp;http-flv-module1.2.7&amp;windows)

    1、nginx-http-flv-module(windows可执行程序,含http-flv-module:1.2.7,nginx 1.19.3) 2、不要放置于中文路径下,否则无法启动 3、说明文档,请下载查看。

    nginx-http-flv-module-1.2.10(包含nginx-rtmp-module)

    而nginx-rtmp-module则是一个额外的Nginx模块,它增加了对Real-Time Messaging Protocol (RTMP)的支持,使Nginx能够作为RTMP服务器接收并分发直播流。 1. **HTTP FLV 模块详解** HTTP FLV模块使得Nginx可以处理FLV...

    (修复bug模块)nginx-http-flv-module-master 支持flv模块直播

    【标题】:“(修复bug模块)nginx-http-flv-module-master 支持flv模块直播” 指的是一个专门针对Nginx服务器的扩展模块,该模块允许Nginx支持流媒体服务,特别是针对FLV(Flash Video)格式的实时流媒体。...

    Nginx模块开发入门

    ### Nginx模块开发入门详解 #### Nginx概述与市场地位 Nginx作为一款高性能的HTTP服务器和反向代理服务器,在全球范围内享有极高的声誉。根据权威机构W3Techs的数据,截至某一时间点,全球排名前100万的网站中,...

    集成了nginx-http-flv-module 1.2.7模块的64位nginx程序

    `nginx-http-flv-module`是一个Nginx的第三方模块,由Arut开发,用于处理HTTP实时流媒体(HTTP Live Streaming,HLS)和Flash Video(FLV)流。通过这个模块,Nginx可以作为RTMP服务器,接收和分发FLV流,使得网页...

Global site tag (gtag.js) - Google Analytics