zoukankan      html  css  js  c++  java
  • Apache模块开发

    一、简介

    Apache HTTP服务器是一个模块化的软件,使管理者可以选择核心中包含的模块以裁剪功能。可以在编译时选择被静态包含进httpd二进制映象的模块,也可以编译成独立于主httpd二进制映象的动态共享对象DSO,DSO模块可以在编译服务器之后编译,也可以用Apache扩展工具(apxs)编译并增加。

    Apache模块开发主要采用挂钩子的方法来实现模块开发的,这和linux内核模块开发有点像,说白了就是加一个回调函数。

    二、安装Apache的apxs

    apxs是一个为Apache HTTP服务器编译和安装扩展模块的工具,用于编译一个或多个源程序或目标代码文件为动态共享对象,使之可以用由mod_so提供的LoadModule指令在运行时加载到Apache服务器中。
     
    apxs参考文档:http://lamp.linux.gov.cn/Apache/ApacheMenu/programs/apxs.html
     
    查看是否有httpd-devel这个包,如果没有需要安装

    #rpm -qa | grep httpd          #查看
    #yum -y install httpd-devel    #安装

    三、开发实例

    程序1:apache模块开发之内容生成器

    执行以下命令,将生成helloworld的模板

    apxs -g -n helloworld

    生成的代码如下:

    /* 
    **  mod_helloworld.c -- Apache sample helloworld module
    **  [Autogenerated via ``apxs -n helloworld -g'']
    **
    **  To play with this sample module first compile it into a
    **  DSO file and install it into Apache's modules directory 
    **  by running:
    **
    **    $ apxs -c -i mod_helloworld.c
    **
    **  Then activate it in Apache's httpd.conf file for instance
    **  for the URL /helloworld in as follows:
    **
    **    #   httpd.conf
    **    LoadModule helloworld_module modules/mod_helloworld.so
    **    <Location /helloworld>
    **    SetHandler helloworld
    **    </Location>
    **
    **  Then after restarting Apache via
    **
    **    $ apachectl restart
    **
    **  you immediately can request the URL /helloworld and watch for the
    **  output of this module. This can be achieved for instance via:
    **
    **    $ lynx -mime_header http://localhost/helloworld 
    **
    **  The output should be similar to the following one:
    **
    **    HTTP/1.1 200 OK
    **    Date: Tue, 31 Mar 1998 14:42:22 GMT
    **    Server: Apache/1.3.4 (Unix)
    **    Connection: close
    **    Content-Type: text/html
    **  
    **    The sample page from mod_helloworld.c
    */ 
    
    #include "httpd.h"
    #include "http_config.h"
    #include "http_protocol.h"
    #include "ap_config.h"
    
    /* The sample content handler */
    static int helloworld_handler(request_rec *r)
    {
        if (strcmp(r->handler, "helloworld")) {
            return DECLINED;
        }
        r->content_type = "text/html";      
    
        if (!r->header_only)
            ap_rputs("The sample page from mod_helloworld.c
    ", r);
        return OK;
    }
    
    static void helloworld_register_hooks(apr_pool_t *p)
    {
        ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE);
    }
    
    /* Dispatch list for API hooks */
    module AP_MODULE_DECLARE_DATA helloworld_module = {
        STANDARD20_MODULE_STUFF, 
        NULL,                  /* create per-dir    config structures */
        NULL,                  /* merge  per-dir    config structures */
        NULL,                  /* create per-server config structures */
        NULL,                  /* merge  per-server config structures */
        NULL,                  /* table of config file commands       */
        helloworld_register_hooks  /* register hooks                      */
    };

    编译

    apxs -c mod_helloworld.c

    安装

    apxs -i mod_helloworld.la

    修改配置文件httpd.conf,以加载模块,主要添加如下内容

    LoadModule helloworld_module modules/mod_helloworld.so
    <Location /helloworld>
       SetHandler helloworld
    </Location>

    重启服务器,进行测试

    apachectl -k stop     #停止
    apachectl -k start    #启动

    在浏览器中输入url,即可看到效果

    image

    程序2:apache模块开发之输出过滤器

    对于过滤器,有输入过滤器与输出过滤器两种,有下面的顺序:

    请求--输入过滤器--内容生成器--输出过滤器--响应

    所有的请求都会经过我们的过滤器,所以我们可以对这些进行操作,比如统计流量、数据压缩等。下面示例可把页面中所有的小写字母变成大写字母。

    /**
     * @file: mod_casefilter.c
     * @brief: 把页面中所有的小写字母变成大写字母
     */
     
    #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
    };

    编译

    apxs -c mod_filter.c

    安装

    apxs -i mod_filter.la

    配置httpd.conf,添加如下内容:

    LoadModule case_filter_module modules/mod_casefilter.so
    CaseFilter on

    测试

    image

  • 相关阅读:
    代码 自动化部署
    java 反射工具
    springBoot 简化读取配置 Configuration Processor
    docker 安装redis
    怎么用mybatis
    shiro框架
    Nginx 负载均衡的几种方式
    CSS Reset
    两种CSS3圆环进度条详解
    兼容全浏览器的本地图片预览
  • 原文地址:https://www.cnblogs.com/274914765qq/p/4453315.html
Copyright © 2011-2022 走看看