`
ithurricane
  • 浏览: 12728 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

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



确认模块安装完毕:
cd /etc/httpd/modules
ls | grep mod_case_filter



在httpd.conf中加入:
LoadModule case_filter_module modules/mod_case_filter.so
<Location /mod_case_filter>
    SetHandler mod_case_filter    
</Location>
CaseFilter on



这个时候访问启动apache,
apachectl restart



访问一个页面看看,发现页面中的每个字符都变成了大写。

这就是filter改变了输出的内容的结果。

这个是一个很好的例子,在这个例子上做一些改变可以很方便的实现自己对所有经过apache出去的内容做更改。

效果图:


简单的介绍一下代码,首先实现几个Apache的钩子,比如:ap_hook_insert_filter和ap_register_output_filter

具体Apache钩子函数的介绍可以参考:
http://httpd.apache.org/docs/2.0/developer/modules.html

然后写filter模块的话 ,有一个非常重要的数据结构apr_bucket

简单的说bucket是流数据的抽象,数据源包括了文件,管道,网络,内存等,抽象化了之后,不管是什么数据源,都统一了操作,

主要可以进行read、split、copy三个操作,

apr_bucket* b ; //当前元素
apr_bucket_brigade* bbin ; //链表

遍历客户端输入的内容内容

  for ( b = APR_BRIGADE_FIRST(bbin) ;
    b != APR_BRIGADE_SENTINEL(bbin) ;
    b = APR_BUCKET_NEXT(b) ) {
{ }
//从当前apr_bucket_brigade中删除apr_bucket,但不释放资源
APR_BUCKET_REMOVE(b);

//从当前apr_bucket_brigade中删除apr_bucket,且释放资源

apr_bucket_delete(b);

输出结果的话有这几个函数apr_brigade_puts(),apr_brigade_printf(),apr_brigade_write(),apr_brigade_putc()

filter模块可以在请求数据可以在到达内容生成器之前被输入过滤器
进行处理,回复数据可以在发送到客户端之前被输出过滤器进行处理。过滤器使得数据处
理的实现比以往的版本更加简洁有效,同时将内容生成器从它的变换(transformation)和

集合(aggregation)中分离出来。



说了这么多,我想 每个真正的Web程序员,有机会都应该看看Apache的源代码,都会有可能要修改甚至新作一个Apache模块的,

不光是Apache,lighttpd和nginx等服务器也是一样的道理,祝大家新年快乐啊!
1
1
分享到:
评论

相关推荐

    opencms9.0.1开发学习笔记资料

    本开发学习笔记旨在记录在使用该版本时遇到的问题及其解决方案,帮助开发者更好地理解和掌握 Opencms 的核心功能。 1. **Opencms 介绍和环境搭建** - **简介**:Opencms 是一个基于 Java 技术的 CMS 平台,它提供...

    Linux_5.4_RHCE_Apache高级配置_学习笔记

    【Linux 5.4 RHCE Apache 高级配置学习笔记】 在Linux 5.4的环境中,Red Hat Certified Engineer (RHCE) 认证需要掌握Apache服务器的高级配置技巧。本学习笔记旨在帮助读者深入理解如何高效管理和优化Apache服务器...

    apache mina 学习笔记三(子项目FtpServer)

    在本学习笔记中,我们将专注于MINA的子项目——FtpServer,它是实现FTP服务器功能的一个模块。 FTP(File Transfer Protocol)是一种广泛使用的互联网协议,用于在不同主机之间传输文件。Apache MINA FtpServer提供...

    Spring MVC 学习笔记 一 创建项目

    **Spring MVC 学习笔记 一 创建项目** 在IT领域,Spring MVC是Java Web开发中的一个强大框架,它简化了构建交互式Web应用程序的过程。本笔记将深入探讨如何创建一个基本的Spring MVC项目,让我们开始吧。 首先,...

    svn学习笔记-windows下安装svn加apache的安装流程

    **描述:** 虽然描述部分为空,但我们可以推测博主在博客中可能详细记录了安装和配置的每一步,包括下载所需软件、安装步骤、设置环境变量、配置Apache模块等关键环节。 **标签:** "源码"和"工具"这两个标签暗示了...

    Apache Web服务器配置与使用工作笔记

    #### 五、Apache模块配置 1. **启用模块** - Apache通过模块来扩展其功能。常用的模块包括`mod_rewrite`(URL重写)、`mod_ssl`(SSL/TLS加密)等。 - 启用模块的方法有两种:一是通过修改`httpd.conf`文件中的`...

    IntraWeb 开发学习笔记

    IntraWeb是一款强大的Web应用程序开发框架,主要用于创建交互式的、基于服务器的富互联网应用...通过深入学习和实践IntraWeb,开发者可以掌握一种高效、灵活的Web开发方法,从而创建出高性能、用户友好的Web应用程序。

    培训机构传出的maven学习笔记

    **正文** Maven是Java开发领域中不可或缺...通过这份学习笔记,初学者将能够快速上手Maven,熟练掌握项目构建流程,提高开发效率。而经验丰富的开发者也能从中学习到新的技巧和最佳实践,提升自身在项目管理中的能力。

    软件测试学习笔记

    ### 软件测试学习笔记知识点详解 #### 一、软件测试基础知识 1. **软件测试定义** - **理解**:软件测试是通过执行软件产品来评估其质量的过程。 - **目的**:确保软件产品能够满足用户的需求并达到预定的质量...

    maven学习笔记

    **Maven学习笔记** 在Java开发领域,Maven是一个不可或缺的构建工具,它极大地简化了项目的构建、管理和依赖管理过程。Maven通过一个统一的项目对象模型(Project Object Model,POM),使得开发者可以轻松地定义...

    tomcat学习笔记

    【标题】:Tomcat学习笔记 【正文】: Tomcat是一款广泛应用的开源Web服务器和Java Servlet容器,由Apache软件基金会的Jakarta项目开发。它实现了Java Servlet和JavaServer Pages(JSP)规范,并且作为轻量级应用...

    ant 学习 笔记 一个简单的java 编译部署实例

    根据提供的文件信息,这里将深入解析“ant学习笔记:一个简单的java编译部署实例”,涵盖标题、描述、标签以及部分内容中提及的关键知识点。 ### Apache Ant简介 Apache Ant是一款开源的Java环境下的自动化构建...

    osgi学习笔记(一)

    OSGi(Open Services Gateway Initiative)学习笔记(一) 在IT领域,OSGi是一种模块化系统和Java服务平台,它提供了一种动态管理软件组件的能力。本文将深入探讨OSGi的基本概念、架构以及如何使用它来构建可扩展和...

    svn学习笔记

    ### SVN学习笔记 #### 版本控制的重要性及概念解析 版本控制在软件开发过程中扮演着极其重要的角色。尤其是在多人协作的环境下,版本控制系统能够有效帮助团队成员管理代码、文档和其他重要资源的不同版本,确保每...

    linux学习笔记--很经典

    本篇“Linux学习笔记”详细介绍了Linux的基本目录结构及其各自的功能,这对于初学者理解Linux系统的核心概念非常重要。 #### 二、Linux目录结构解析 1. **/(根目录)** - 根目录是Linux文件系统的起点,所有的...

    struts2学习笔记

    以上就是Struts2学习笔记中涵盖的主要知识点,这些内容涵盖了从基础到进阶的应用,对于理解和掌握Struts2框架至关重要。尽管对于初学者来说可能有些复杂,但随着深入学习,你会发现Struts2的强大和实用性。

    Nginx学习笔记.zip

    这个“Nginx学习笔记.zip”压缩包文件包含了一系列关于Nginx的教程资源,分别命名为“第1节课”到“第5节课”,暗示着一个逐步深入的学习过程。 在第一节课中,我们通常会了解Nginx的基本概念和安装步骤。Nginx的...

    php-laravel框架学习笔记1.doc

    同时还要启动 Apache 的 rewrite 模块后需要重启 Apache。 五、Laravel 框架的路由规则 Laravel 框架有一个很特别的地方,所有的 url 的访问都必须要事先定义好一个路由规则。对比之前的 TP|CI 框架 index....

    Maven中文开发指南+实战教程+学习笔记

    **Maven学习笔记** 1. **高级特性** - Maven Profiles允许根据环境条件选择不同的配置。 - Inheritance和Aggregation进一步优化POM管理,减少重复配置。 - Maven的远程资源插件可以集成外部资源,如配置文件。 ...

Global site tag (gtag.js) - Google Analytics