前面写了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是差不多的,只是做了一些优化。
分享到:
相关推荐
本篇文章将深入探讨Apache模块开发的基本概念、流程以及一个名为"adservice"的示例模块。 一、Apache模块开发基础 1. 模块结构:Apache模块通常由一组函数组成,这些函数在特定的Apache钩子(hooks)上执行,以...
例如,输入过滤器处理请求数据,输出过滤器处理响应数据,而请求处理器则负责实际的工作。 6. **日志和错误处理**:模块开发中,记录日志和处理错误是必不可少的。学会如何使用ap_log_error函数和控制日志级别,...
过滤器是Apache处理输入和输出内容的重要工具。它们可以对HTTP请求和响应进行修改,如内容编码、压缩、安全检查等。Apache提供了多种内置过滤器,如处理网络数据的CORE_IN和CORE过滤器,以及处理Chunk编码的Chunk...
2. **Apache Commons IO**: IO库是处理输入/输出操作的基石,它包含了文件读写、流操作、过滤器、转换器等功能。例如,FileUtils类提供了文件和目录的操作,如复制、移动、删除等,而IOUtils则有读取和写入流的便捷...
此函数用于在HTTP响应流上添加一个输出过滤器,可以对即将发送给客户端的数据进行处理,如压缩、加密等。 在实践中,这些函数通常结合使用,以实现更复杂的服务器端功能。例如,你可能会使用`ap_is_initial_request...
此外,Log4j还支持自定义布局和过滤器,以满足特定的应用场景。 在提供的文件列表中,我们看到有`apache-log4j-1.2.15.tar.gz`,这是Log4j的一个版本,1.2.15是其发行版本号。Log4j的更新版本可能包含更多的功能和...
Apache MINA(Multipurpose Infrastructure for Network Applications)是一个Java框架,专为开发高性能和高可用性的网络应用程序而设计。MINA提供了异步的、事件驱动的网络应用编程接口(API),适用于TCP和UDP协议...
Apache Commons库主要由一系列模块组成,每个模块专注于特定的功能领域,如IO(输入/输出)、Lang(语言工具)、Collections(集合操作)、Math(数学运算)等。以下是一些关键模块及其主要功能: 1. **Apache ...
3. **丰富的过滤器体系**:MINA采用过滤器链的设计模式,允许开发者插入自定义的过滤器来处理输入和输出数据,实现数据编码、解码、安全加密等功能。 4. **多协议支持**:MINA可以轻松地支持各种网络协议,如TCP、...
6. **过滤器(Filter)**:提供了一种机制,可以在日志事件被处理之前进行过滤,例如基于日志级别、源类或特定关键字进行过滤。 7. **Lookups**:Lookups允许在配置文件中动态获取值,如系统属性、环境变量等,增强...
2. **Filter Chain**:MINA采用过滤器链模式,允许开发者通过添加、删除或定制过滤器来处理输入和输出数据。过滤器可以用于数据编码、解码、安全加密、流量控制等多种任务。 3. **Handler**:处理器是用户自定义的...
2. **Commons IO**:处理输入/输出流操作,提供了一些方便的文件操作类和流处理类,例如文件复制、读写、过滤等功能。 3. **Commons BeanUtils**:简化对象属性的访问和操作,提供了自动类型转换和基于属性名的操作...
1. **Servlet 2.5规范**:提供了更多的API扩展,增强了对HTTP协议的支持,如更好的处理PUT和DELETE请求,以及改进的过滤器链管理。 2. **JSP 2.1规范**:引入了表达式语言(EL)2.1,增强了JSP页面的可读性和可维护...
2. **可扩展的过滤器链**:MINA引入了过滤器的概念,允许开发者通过组合过滤器来实现复杂的功能。过滤器可以处理数据的编码、解码、安全性和性能优化等任务,使业务逻辑与网络细节分离。 3. **跨平台兼容性**:由于...
【Apache Tomcat 8.5.11 源代码详解】 ...通过深入研究 Apache Tomcat 8.5.11 的源代码,开发者可以更好地理解 Web 服务器的工作机制,提升解决问题的能力,同时也为开发自定义的 Web 服务提供了可能。
本篇文章将详细讲解几个重要的 Apache Commons 模块,包括 Apache Commons Email、Apache Commons IO、Apache Commons Pool、Apache Commons DBCP、Apache Commons Dbutils 和 Apache Commons Collections,以及 ...
- **输出过滤器**: 对响应数据进行后处理。 **19. suEXEC 支持** - **权限隔离**: 使每个用户只能执行自己的脚本。 - **安全性增强**: 减少服务器受到攻击的风险。 **20. Apache 性能调优** - **内存管理**: 优化...
在给定的压缩包文件"commons_help"中,可能包含了这些模块的API文档,这些文档可以帮助开发者更深入地理解每个组件的功能和用法,从而更好地利用Apache Commons进行开发工作。通过查阅这些文档,你可以快速查找所需...
8. **扩展性**:Tomcat 7允许添加自定义的JAR文件到`lib`目录,以扩展其功能,或者实现特定的拦截器、过滤器等。 9. **版本兼容性**:虽然`apache-tomcat-7.0.42`支持Java EE 6,但请注意,它同样兼容Java 7和8。...
3. **模块化架构**:支持多种过滤器,如gzipping、byteranges、chunked responses和SSI-filter。 4. **并发连接处理**:支持高达50,000个并发连接数。 5. **稳定性**:Nginx以其高稳定性和可靠性而闻名。 6. **高...