前面写了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是差不多的,只是做了一些优化。
分享到:
相关推荐
注:本系列图书的第I、II卷再版时均相应改名为《xxx开发实例大全》(基础卷)及(提高卷),但内容基本无变化,需要的童鞋可自由匹配查找。 内容简介 《PHP开发实战1200例》分为I、II两卷共计1200个例子,包括了开发...
注:本系列图书的第I、II卷再版时均相应改名为《xxx开发实例大全》(基础卷)及(提高卷),但内容基本无变化,需要的童鞋可自由匹配查找。 内容简介 《PHP开发实战1200例》分为I、II两卷共计1200个例子,包括了开发...
1.6 几种开发工具的介绍 20 1.6.1 Vi及Vim 20 1.6.2 Eclipse+PHPEclipse插件 21 1.6.3 UltraEdit 21 1.6.4 EditPlus 22 1.6.5 支持PHP的IDE环境 22 1.7 小结 23 第2章 PHP的基础语法 24 2.1 语言构成与工作原理 24 ...
Java数据压缩与传输实例,可以学习一下实例化套按字、得到文件输入流、压缩输入流、文件输出流、实例化缓冲区、写入数据到文件、关闭输入流、关闭套接字关闭输出流、输出错误信息等Java编程小技巧。 Java数组倒置...
Java数据压缩与传输实例,可以学习一下实例化套按字、得到文件输入流、压缩输入流、文件输出流、实例化缓冲区、写入数据到文件、关闭输入流、关闭套接字关闭输出流、输出错误信息等Java编程小技巧。 Java数组倒置...
可用过滤器列表 O. 所支持的套接字传输器(Socket Transports)列表 P. PHP 类型比较表 Q. 解析器代号列表 R. 关于本手册 S. 开放出版许可协议 T. 函数索引 X. CHM 版本 62. 关于此版本 63. Using ...
平台分类器 11.8. 小结 12. Maven Assemblies 12.1. Introduction 12.2. Assembly Basics 12.2.1. Predefined Assembly Descriptors 12.2.2. Building an Assembly 12.2.3. Assemblies as Dependencies ...
10-25 4 内容过滤器 可见度过滤器及练习讲解 10-26 1 课程回顾 10-26 2 属性过滤选择器 10-26 3 子元素选择器 表单对象属性选择器 10-26 4 jquery对象集合遍历的四种形式及练习题讲解 jquery的dom操作 10-27 1课程...
10-25 4 内容过滤器 可见度过滤器及练习讲解 10-26 1 课程回顾 10-26 2 属性过滤选择器 10-26 3 子元素选择器 表单对象属性选择器 10-26 4 jquery对象集合遍历的四种形式及练习题讲解 jquery的dom操作 10-27 1课程...
10-25 4 内容过滤器 可见度过滤器及练习讲解 10-26 1 课程回顾 10-26 2 属性过滤选择器 10-26 3 子元素选择器 表单对象属性选择器 10-26 4 jquery对象集合遍历的四种形式及练习题讲解 jquery的dom操作 10-27 1课程...
10-25 4 内容过滤器 可见度过滤器及练习讲解 10-26 1 课程回顾 10-26 2 属性过滤选择器 10-26 3 子元素选择器 表单对象属性选择器 10-26 4 jquery对象集合遍历的四种形式及练习题讲解 jquery的dom操作 10-27 1课程...
10-25 4 内容过滤器 可见度过滤器及练习讲解 10-26 1 课程回顾 10-26 2 属性过滤选择器 10-26 3 子元素选择器 表单对象属性选择器 10-26 4 jquery对象集合遍历的四种形式及练习题讲解 jquery的dom操作 10-27 1课程...
� 源代码完全开放,便于开发人员更清楚的把握实现细节,便于提高开发人员的技术水平,有利于开发 出 更具差异性的应用。 � 采用了对有限内存、电池和 CPU 优化过的虚拟机 Dalvik , Android 的运行速度比想象的要...
可用过滤器列表 O. 所支持的套接字传输器(Socket Transports)列表 P. PHP 类型比较表 Q. 解析器代号列表 R. 关于本手册 S. 开放出版许可协议 T. 函数索引 X. CHM 版本 62. 关于此版本 63. Using ...
可用过滤器列表 Q. 所支持的套接字传输器(Socket Transports)列表 R. PHP 类型比较表 S. 解析器代号列表 T. Userland Naming Guide U. 关于本手册 V. 开放出版许可协议 W. 函数索引 X. 补充说明 X. CHM 版本 73. ...
对于那些仅封装了Connection而未包括Statement的简单数据连接池,SimpleNativeJdbcExtractor是效率最高的抽取器实现类,但具体到apache的BasicDataSource连接池,它封装了所有JDBC的对象,这时就需要使用...
- Kodexplorer为千帆网络工作室开发的一款服务器文件管理程序。 - 完美取代FTP管理:可用于服务器文件管理,zip解压缩 备份还原、支持图片、音乐、视频预览、office、pdf等格式在线预览。文件夹拖拽上传……。 - ...