本博文是总结《Apache模块开发》中的第5章
mod_helloworld是一个非常简单的模块,仅仅完成内容展示工作。但是它却可以展示编写Apache模块的基本框架。
我的开发环境是ubuntu 10.04 amd64 server,apache版本是2.2.15
module AP_MODULE_DECLARE_DATA some_module = { STANDARD20_MODULE_STUFF, some_dir_cfg, /* create per-directory config struct */ some_dir_merge, /* merge per-directory config struct */ some_svr_cfg, /* create per-host config struct */ some_svr_merge, /* merge per-host config struct */ some_cmds, /* configuration directives for this module */ some_hooks /* register module's hooks/etc. with the core */ };STANDARD20_MODULE_STUFF宏展开,它提供了模块的版本信息。在这里我们不对他做深入的研究,有兴趣了解的可以阅读Apache的源代码。
module AP_MODULE_DECLARE_DATA helloworld_module = { STANDARD20_MODULE_STUFF, NULL, NULL, NULL, NULL, NULL, helloworld_hooks };现在我们来写钩子注册函数,它会在Apache服务启动时调用。它的用途是把我们的处理函数注册给服务器核心(server core),这样模块的函数就会在适当的时机得到调用。对于helloworld来说,我们这样仅仅注册一个”内容生成“类型的钩子(Apache有很多类型的钩子)
static void helloworld_hooks(apr_pool_t *pool) { ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE); }最后当然是实现处理函数helloworld_handler啦。它是一个回调函数,他会在Apache处理HTTP请求的适当时机调用。处理函数可以选择处理或是忽略这个请求。
static int helloworld_handler(request_rec *r) { if (!r->handler || strcmp(r->handler, "helloworld")) { return DECLINED; } if (r->method_number != M_GET) { return HTTP_METHOD_NOT_ALLOWED; } ap_set_content_type(r, "text/html;charset=ascii"); ap_rputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n", r); ap_rputs("<html><head><title>Hello Apache Module</title></head>", r); ap_rputs("<body><h1>Hello Apache Module</h1>", r); ap_rputs("</body></html>", r); return OK; }我们开始做一些检查,来决定模块是处理这个请求还是忽略它。返回DECLINED表示忽略,OK表示成功处理,也可返回HTTP状态代码(HTTP status code)表示错误处理。
/* The simplest HelloWorld module */ #include <httpd.h> #include <http_protocol.h> #include <http_config.h> static int helloworld_handler(request_rec *r) { if (!r->handler || strcmp(r->handler, "helloworld")) { return DECLINED; } if (r->method_number != M_GET) { return HTTP_METHOD_NOT_ALLOWED; } ap_set_content_type(r, "text/html;charset=ascii"); ap_rputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n", r); ap_rputs("<html><head><title>Hello Apache Module</title></head>", r); ap_rputs("<body><h1>Hello Apache Module</h1>", r); ap_rputs("</body></html>", r); return OK; } static void helloworld_hooks(apr_pool_t *pool) { ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE); } module AP_MODULE_DECLARE_DATA helloworld_module = { STANDARD20_MODULE_STUFF, NULL, NULL, NULL, NULL, NULL, helloworld_hooks };
/usr/local/apache2/bin/apxs -iac mod_helloworld.c这样我们的modules目录中就多了一个mod_helloworld.so的文件
LoadModule helloworld_module modules/mod_helloworld.so <Location /helloworld> SetHandler helloworld </Location>第一行是让Apache动态的载入这个模块。