`
andrew913
  • 浏览: 188823 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

apache 模块开发之输出过滤器

阅读更多
前面写了apache模块开发之hellloworld ,那个例子是一个简单的内容生成器。现在我们来讲一个过滤器的实现。过滤器是apache中一个非常精妙的设计,apache自带的很多模块都是通过过滤器来实现。

对于过滤器,有输入过滤器与输出过滤器两种。
对于输入过滤器,就是在内容生成器之前执行,而输出过滤器则在内容生成器之后。可以有下面的顺序:
http请求-》输入过滤器-》内容生成-》输出过滤器-》用户

所有的请求都会经过我们的过滤器,所以我们可以对这些进行操作,比如统计流量,压缩等等。

下面我们讲一个例子,这个例子是apache自带的一个demo,它的功能是把页面中所有的小写字母变成大写字母。
从上面的过滤器流程中我们可以找到,只要我们在输出过滤器中挂一个钩子,然后将所有的字符变成大写就OK了。
代码如下:
#include "httpd.h"
#include "http_config.h"
#include "apr_buckets.h"
#include "apr_general.h"
#include "apr_lib.h"
#include "util_filter.h"
#include "http_request.h"

#include <ctype.h>

static const char s_szCaseFilterName[]="CaseFilter";
module AP_MODULE_DECLARE_DATA case_filter_module;

typedef struct
{
    int bEnabled;
} CaseFilterConfig;

static void *CaseFilterCreateServerConfig(apr_pool_t *p,server_rec *s)
{
    CaseFilterConfig *pConfig=apr_pcalloc(p,sizeof *pConfig);

    pConfig->bEnabled=0;

    return pConfig;
}

static void CaseFilterInsertFilter(request_rec *r)
{
    CaseFilterConfig *pConfig=ap_get_module_config(r->server->module_config,
                              &case_filter_module);

    if (!pConfig->bEnabled)
        return;

    ap_add_output_filter(s_szCaseFilterName,NULL,r,r->connection);
}

static apr_status_t CaseFilterOutFilter(ap_filter_t *f,
                                        apr_bucket_brigade *pbbIn)
{
    request_rec *r = f->r;
    conn_rec *c = r->connection;
    apr_bucket *pbktIn;
    apr_bucket_brigade *pbbOut;

    pbbOut=apr_brigade_create(r->pool, c->bucket_alloc);
    for (pbktIn = APR_BRIGADE_FIRST(pbbIn);
            pbktIn != APR_BRIGADE_SENTINEL(pbbIn);
            pbktIn = APR_BUCKET_NEXT(pbktIn))
    {
        const char *data;
        apr_size_t len;
        char *buf;
        apr_size_t n;
        apr_bucket *pbktOut;

        if (APR_BUCKET_IS_EOS(pbktIn))
        {
            apr_bucket *pbktEOS=apr_bucket_eos_create(c->bucket_alloc);
            APR_BRIGADE_INSERT_TAIL(pbbOut,pbktEOS);
            continue;
        }

        /* read */
        apr_bucket_read(pbktIn,&data,&len,APR_BLOCK_READ);

        /* write */
        buf = apr_bucket_alloc(len, c->bucket_alloc);
        for (n=0 ; n < len ; ++n)
            buf[n] = apr_toupper(data[n]);

        pbktOut = apr_bucket_heap_create(buf, len, apr_bucket_free,
                                         c->bucket_alloc);
        APR_BRIGADE_INSERT_TAIL(pbbOut,pbktOut);
    }
    apr_brigade_cleanup(pbbIn);
    return ap_pass_brigade(f->next,pbbOut);
}

static const char *CaseFilterEnable(cmd_parms *cmd, void *dummy, int arg)
{
    CaseFilterConfig *pConfig=ap_get_module_config(cmd->server->module_config,
                              &case_filter_module);
    pConfig->bEnabled=arg;

    return NULL;
}

static const command_rec CaseFilterCmds[] =
{
    AP_INIT_FLAG("CaseFilter", CaseFilterEnable, NULL, RSRC_CONF,
    "Run a case filter on this host"),
    { NULL }
};

static void CaseFilterRegisterHooks(apr_pool_t *p)
{
    ap_hook_insert_filter(CaseFilterInsertFilter,NULL,NULL,APR_HOOK_MIDDLE);
    ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter,NULL,
                              AP_FTYPE_RESOURCE);
}

module AP_MODULE_DECLARE_DATA case_filter_module =
{
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    CaseFilterCreateServerConfig,
    NULL,
    CaseFilterCmds,
    CaseFilterRegisterHooks
};


首先所有程序的入口还是case_filter_module这个变量,它和之前的helloworld多了几个选项,其中CaseFilterCreateServerConfig这是一个服务器初始化函数,这个初始化会在apache启动的时候执行。
我们来看下具体的实现:

static void *CaseFilterCreateServerConfig(apr_pool_t *p,server_rec *s)
{
    CaseFilterConfig *pConfig=apr_pcalloc(p,sizeof *pConfig);
    pConfig->bEnabled=0;
    return pConfig;
}



这里我们需要讲一下在apache中申请内存空间和普通的c语言的malloc有所区别,apache的申请空间都是向池申请,然后在这个池消失的时候就自动的释放我们的空间。其效率也要高于我们普通c语言malloc的堆空间分配的。
具体语法:
CaseFilterConfig *pConfig=apr_pcalloc(p,sizeof *pConfig);


这里就是向p这个池申请了空间,这个变量初始化以后,它的生命周期是等同于整个httpd进程的。所以在我们后面的程序中都可以调用。

case_filter_module这个变量还有CaseFilterCmds这个变量,这是一个配置命令,也就是说当我们想把一些参数通过配置httpd.conf来传入apache的时候,我们就通过这个函数指针。
它的结构为:
static const command_rec CaseFilterCmds[] =
{
    AP_INIT_FLAG("CaseFilter", CaseFilterEnable, NULL, RSRC_CONF,
    "Run a case filter on this host"),
    { NULL }
};


变量第一个参数为我们配置的选项,也就是我们的key,第二个参数是这个配置命令将执行的函数,我们就是通过这个函数来传递我们的配置的。例如本例子我们需要在httpd.conf中加入CaseFilter on这个命令,我们也可以看到CaseFilterEnable的实现为:

static const char *CaseFilterEnable(cmd_parms *cmd, void *dummy, int arg)
{
    CaseFilterConfig *pConfig=ap_get_module_config(cmd->server->module_config,
                              &case_filter_module);//读配置
    pConfig->bEnabled=arg;//传递配置
    return NULL;
}


case_filter_module最后一个参数就是我们的注册函数,具体实现如下:
static void CaseFilterRegisterHooks(apr_pool_t *p)
{
    ap_hook_insert_filter(CaseFilterInsertFilter,NULL,NULL,APR_HOOK_MIDDLE);
    ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter,NULL,
                              AP_FTYPE_RESOURCE);
}


ap_hook_insert_filter 就是通过CaseFilterInsertFilter来讲我们的过滤器加入到apache过滤链中,然后就是ap_register_output_filter这个函数将我们的过滤器模块注册起来。
当我们需要输出一个页面的时候,就会触发ap_register_output_filter中低二个参数,这个参数为我们的处理函数指针,也就是我们所有的操作都是可以在这里搞定。对于这里,我们把所有的小写字母转化为大写字母,当然我们可以做更多的事情。

最后我们在我们的httpd.conf中加入

Loadmodule******//加载我们的模块

再加上我们的配置命令
CaseFilter on  //开启我们的过滤模块,我们也可以加入很多类似的配置。

编译我们的模块,重新启动apache,在看看我们的apache中所有的页面中的小写变成了大写。

最后还需要讲一点的时候,上面用的很多函数和标准C是有区别的,都是调用的apr的库。所以我们还要去熟悉下这里的函数,总体来说和标准C是差不多的,只是做了一些优化。

4
0
分享到:
评论
2 楼 andrew913 2009-06-02  
apache的struts啊?
rrsy23 写道

总的觉得开发配置思想和今天java平台的 tomcat,servlet,spring,servicemix差不多;呵呵也许tomcat本copy apache 何况后者其他户;所以学习还是学其神其思;不过开发配置还是比高级语言平台麻烦啰嗦;呵呵LZ可以考虑自己加一层通过配置文件解决问题;我们开发servlet麻烦 有struts为什么不开发个apache的struts啊?lz可以考虑哦;就是自己定义规则[配置简化],然后apache加载你的体系,你去加载其他的 模块最早;我写过类似的一个小东西;

我对Java开发不是很熟,不是很明白你的意思,以是做底层开发的,只是最近要搞apache监控模块.比如限制某个虚拟主机的流量,监控它的cpu占用率等,相对来说不是很面向业务逻辑的。
1 楼 rrsy23 2009-06-02  
总的觉得开发配置思想和今天java平台的 tomcat,servlet,spring,servicemix差不多;

呵呵也许tomcat本copy apache 何况后者其他户;

所以学习还是学其神其思;

不过开发配置还是比高级语言平台麻烦啰嗦;


呵呵LZ可以考虑自己加一层通过配置文件解决问题;

我们开发servlet麻烦 有struts

为什么不开发个apache的struts啊?

lz可以考虑哦;

就是自己定义规则[配置简化],然后apache加载你的体系,你去加载其他的 模块

最早;我写过类似的一个小东西;

相关推荐

    apache 模块开发的例子

    本篇文章将深入探讨Apache模块开发的基本概念、流程以及一个名为"adservice"的示例模块。 一、Apache模块开发基础 1. 模块结构:Apache模块通常由一组函数组成,这些函数在特定的Apache钩子(hooks)上执行,以...

    Apache模块开发指南

    例如,输入过滤器处理请求数据,输出过滤器处理响应数据,而请求处理器则负责实际的工作。 6. **日志和错误处理**:模块开发中,记录日志和处理错误是必不可少的。学会如何使用ap_log_error函数和控制日志级别,...

    Apache 学习路线

    过滤器是Apache处理输入和输出内容的重要工具。它们可以对HTTP请求和响应进行修改,如内容编码、压缩、安全检查等。Apache提供了多种内置过滤器,如处理网络数据的CORE_IN和CORE过滤器,以及处理Chunk编码的Chunk...

    apache commons 开源工具列举

    2. **Apache Commons IO**: IO库是处理输入/输出操作的基石,它包含了文件读写、流操作、过滤器、转换器等功能。例如,FileUtils类提供了文件和目录的操作,如复制、移动、删除等,而IOUtils则有读取和写入流的便捷...

    Apache函数共9个实例代码

    此函数用于在HTTP响应流上添加一个输出过滤器,可以对即将发送给客户端的数据进行处理,如压缩、加密等。 在实践中,这些函数通常结合使用,以实现更复杂的服务器端功能。例如,你可能会使用`ap_is_initial_request...

    apache apr & log4

    此外,Log4j还支持自定义布局和过滤器,以满足特定的应用场景。 在提供的文件列表中,我们看到有`apache-log4j-1.2.15.tar.gz`,这是Log4j的一个版本,1.2.15是其发行版本号。Log4j的更新版本可能包含更多的功能和...

    apache-mina源码

    Apache MINA(Multipurpose Infrastructure for Network Applications)是一个Java框架,专为开发高性能和高可用性的网络应用程序而设计。MINA提供了异步的、事件驱动的网络应用编程接口(API),适用于TCP和UDP协议...

    Apache Commons书籍

    Apache Commons库主要由一系列模块组成,每个模块专注于特定的功能领域,如IO(输入/输出)、Lang(语言工具)、Collections(集合操作)、Math(数学运算)等。以下是一些关键模块及其主要功能: 1. **Apache ...

    apache-mina-3.0.0-M2-src.zip

    3. **丰富的过滤器体系**:MINA采用过滤器链的设计模式,允许开发者插入自定义的过滤器来处理输入和输出数据,实现数据编码、解码、安全加密等功能。 4. **多协议支持**:MINA可以轻松地支持各种网络协议,如TCP、...

    apache-log4j-1.2.15.jar

    6. **过滤器(Filter)**:提供了一种机制,可以在日志事件被处理之前进行过滤,例如基于日志级别、源类或特定关键字进行过滤。 7. **Lookups**:Lookups允许在配置文件中动态获取值,如系统属性、环境变量等,增强...

    apache网络框架mina简介

    2. **Filter Chain**:MINA采用过滤器链模式,允许开发者通过添加、删除或定制过滤器来处理输入和输出数据。过滤器可以用于数据编码、解码、安全加密、流量控制等多种任务。 3. **Handler**:处理器是用户自定义的...

    org.apache.commons jar包大全

    2. **Commons IO**:处理输入/输出流操作,提供了一些方便的文件操作类和流处理类,例如文件复制、读写、过滤等功能。 3. **Commons BeanUtils**:简化对象属性的访问和操作,提供了自动类型转换和基于属性名的操作...

    apache-tomcat-6.0~7.0版本

    1. **Servlet 2.5规范**:提供了更多的API扩展,增强了对HTTP协议的支持,如更好的处理PUT和DELETE请求,以及改进的过滤器链管理。 2. **JSP 2.1规范**:引入了表达式语言(EL)2.1,增强了JSP页面的可读性和可维护...

    apache mina

    2. **可扩展的过滤器链**:MINA引入了过滤器的概念,允许开发者通过组合过滤器来实现复杂的功能。过滤器可以处理数据的编码、解码、安全性和性能优化等任务,使业务逻辑与网络细节分离。 3. **跨平台兼容性**:由于...

    apache-tomcat-8.5.11-src

    【Apache Tomcat 8.5.11 源代码详解】 ...通过深入研究 Apache Tomcat 8.5.11 的源代码,开发者可以更好地理解 Web 服务器的工作机制,提升解决问题的能力,同时也为开发自定义的 Web 服务提供了可能。

    Apache Commons 包的使用

    本篇文章将详细讲解几个重要的 Apache Commons 模块,包括 Apache Commons Email、Apache Commons IO、Apache Commons Pool、Apache Commons DBCP、Apache Commons Dbutils 和 Apache Commons Collections,以及 ...

    Apache server document 2.2

    - **输出过滤器**: 对响应数据进行后处理。 **19. suEXEC 支持** - **权限隔离**: 使每个用户只能执行自己的脚本。 - **安全性增强**: 减少服务器受到攻击的风险。 **20. Apache 性能调优** - **内存管理**: 优化...

    org.apache.commons

    在给定的压缩包文件"commons_help"中,可能包含了这些模块的API文档,这些文档可以帮助开发者更深入地理解每个组件的功能和用法,从而更好地利用Apache Commons进行开发工作。通过查阅这些文档,你可以快速查找所需...

    apache-tomcat-7.0.42.zip

    8. **扩展性**:Tomcat 7允许添加自定义的JAR文件到`lib`目录,以扩展其功能,或者实现特定的拦截器、过滤器等。 9. **版本兼容性**:虽然`apache-tomcat-7.0.42`支持Java EE 6,但请注意,它同样兼容Java 7和8。...

    三大WEB服务器对比分析(apache-apache-nginx)

    3. **模块化架构**:支持多种过滤器,如gzipping、byteranges、chunked responses和SSI-filter。 4. **并发连接处理**:支持高达50,000个并发连接数。 5. **稳定性**:Nginx以其高稳定性和可靠性而闻名。 6. **高...

Global site tag (gtag.js) - Google Analytics