Chinaunix首页 | 论坛 | 博客
  • 博客访问: 402281
  • 博文数量: 87
  • 博客积分: 2571
  • 博客等级: 少校
  • 技术积分: 920
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-29 13:10
文章分类

全部博文(87)

文章存档

2012年(49)

2011年(7)

2010年(26)

2009年(5)

分类: LINUX

2010-04-14 16:29:51

//mod_case_filter.c
//一个将页面内容从小写改为大些的简单filter实例


#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"


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 */

     //data用于存放数据,对于内容的操作基于此
     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);
   }

   /* XXX: is there any advantage to passing a brigade for each bucket? */
   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)
{
   // 插入filter

   ap_hook_insert_filter(CaseFilterInsertFilter,NULL,NULL,APR_HOOK_MIDDLE);
   // 注册filter

   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 //注册output filter
};


安装方法:

  1. ./bin/apxs -c ./mod_case_filter.c
  2. ./bin/apxs -a -i -n case_filter ./mod_case_filter.la

在httpd.conf中加入:

  1. CaseFilter on

重启apache

  [完成]

 

-------------------------------------------------------

 filter类型

util_filter.h中有定义:

typedef enum {
   /** 修改数据内容.如SSI和PHP*/
   AP_FTYPE_RESOURCE = 10,
   /** 将内容当做一个整体来处理,但在AP_FTYPE_RESOURCE 之后执行.如deflate*/
   AP_FTYPE_CONTENT_SET = 20,
   /** 用于处理协议(在server和client之间).如 HTTP 和 POP. */
   AP_FTYPE_PROTOCOL = 30,
   /** 处理编码.如 chunking). */
   AP_FTYPE_TRANSCODE = 40,
   /** 处理内容,但与连接相关.比如(1)将HTTP连接分割为多个请求;(2)缓冲多个请求构成的HTTP响应.
     

   * It is important to note that these types of filters are not
   * allowed in a sub-request. A sub-request’s output can certainly
   * be filtered by ::AP_FTYPE_RESOURCE filters, but all of the "final processing" is determined by the main request. */

   AP_FTYPE_CONNECTION = 50,
   /** 不处理内容,负责与client之间的发送/接受 */
   AP_FTYPE_NETWORK = 60
} ap_filter_type;


 
filter执行顺序
1.按照ap_filter_type从小到大的顺序执行
  也可以这样定义filter:
     ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter,NULL, AP_FTYPE_RESOURCE-1);
  这时filter将会在所有AP_FTYPE_RESOURCE filter前面执行.
 
2.如果两个filter都属于一个级别的filter,比如都属于AP_FTYPE_RESOURCE,那么按照httpd.conf中:
    LoadModule php5_module modules/libphp5.so
    LoadModule case_filter_module modules/mod_case_filter.so 
  的先后顺序依次执行各个filter.
 
filter中用到的重要数据结构
 
apr_bucket_brigade *pbbOut; // 这个东西把所有的输入或者输出串起来,类似于一个链表
apr_bucket *pbktIn; // 这个东西就是链表中的一个元素
 
apache提供很多的宏对这两个结构做处理.
比如:
   // 遍历输出内容
   for (pbktIn = APR_BRIGADE_FIRST(pbbIn);
     pbktIn != APR_BRIGADE_SENTINEL(pbbIn);
     pbktIn = APR_BUCKET_NEXT(pbktIn))
   {
       ...
   }
  
   // 得到下一个bucket
   apr_bucket *newb = APR_BUCKET_NEXT(pbktIn);
  
   //从当前apr_bucket_brigade中删除apr_bucket,但不释放资源
   APR_BUCKET_REMOVE(pbktIn);
  
   //从当前apr_bucket_brigade中删除apr_bucket,且释放资源
   apr_bucket_delete(pbktIn);
  
   对于一个apr_bucket,你可以做split,分割成多个apr_bucket,方便你修改数据.
   比如:
   int index;
   apr_bucket_split(pbktIn, index); //从pbktIn的index位置开始分裂
阅读(2533) | 评论(0) | 转发(0) |
0

上一篇:[stl]auto_ptr

下一篇:[apache]缓存原理

给主人留下些什么吧!~~