日期:2014-05-16  浏览次数:20797 次

Apache模块开发学习笔记(一)
先祝大家2009年心想事成,万事如意,工作顺利,心情愉快啊!



最近开始研究Apache模块的开发,在博客里记录一下学习的过程吧,

本来没什么头绪,现在研究下来,

主要学习Apache的基础对象和 API头文件,例如http_头文件里的函数,

APR(Apache Portable Runtime)函数库,请求处理流程,过滤器架构,页面内容生成等等

我是在Fedora10上开发的,现介绍一下环境的搭建:
# yum install httpd-devel
# yum install automake autoconf
# yum install libtool
# yum install ImageMagick
# yum install ImageMagick-devel
# yum install pcre-devel



现在看一个apache2自带的一个非常简单的filter:

首先创建一个Module工程
cd /usr/local/src
mkdir modtest
cd modtest
apxs -g -n case_filter



自动声称如下文件:
ls -a ./test
.  ..  .deps  Makefile  case_filter.c  modules.mk



修改case_filter.c,代码如下:
#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 */
        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) {
    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
};



然后编译:
apxs -c -i mod_case_filter



确认模块安装完毕: