Apache2.4 模块开发初探
一、开发文档
Apache 的开发文档:http://httpd.apache.org/docs/2.2/zh-cn/developer/
二、、安装Apache
系统 Ubuntu 20.04.2 LTS
我这里使用的宝塔一键安装的编译环境的Apache2.4
三、开发案例
/www/server/apache/bin/apxs -g -n helloworld
这里会帮你生成三个文件
mod_helloworld.c 这个是主文件
/* ** 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\n", 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 */ };
先看看这个注释是什么意思吧
注释说明是怎么使用这个hello world 这个模块 通过apxs -c 的方式编译这个模块
apxs -c -i mod_helloworld.c
然后通过在配置文件中添加配置
LoadModule helloworld_module modules/mod_helloworld.so <Location /helloworld> SetHandler helloworld </Location>
之后重启apache 然后访问 http://localhost/helloworld
就能看到当前模块的效果
尝试测试一下他的说明
然后在配置文件增加配置
测试访问一下
已经成功返回了演示中的字符串
四: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 };
访问一下
全部字符串变为大写了
以上代码的逻辑为:
加载 case_filter_module 模块,通过 CaseFilterRegisterHooks 注册过滤函数 CaseFilterOutFilter。
相关链接:
http://httpd.apache.org/docs/2.0/filter.html 介绍了 filter 可接受的配置指令。
https://www.cnblogs.com/274914765qq/p/4453315.html
https://www.cnblogs.com/diylab/archive/2011/05/05/2037415.html