尝试制作Apache模块
以下内容是转载自2010年2月5日的过去博客。请注意该内容可能已经过时。
我调查了有关Apache模块的制作方法,并总结了一下。
以下是参考的网站:
* module.jp
* 抜きん出て日记
* daily dayflower
* DSAS开发者的房间
我使用的环境是FreeBSD 7.2-RELEASE和Apache/2.2.11。
制作原型
当使用apxs命令并指定-g选项时,它会为模块生成一个大致的模板。通过-n选项可以指定模块的名称。
apxs -g -n sample
生成后的源代码如下。由于太长,因此已删除部分注释。
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
static int sample_handler(request_rec *r)
{
if (strcmp(r->handler, "sample")) {
return DECLINED;
}
r->content_type = "text/html";
if (!r->header_only)
ap_rputs("The sample page from mod_sample.c\n", r);
return OK;
}
static void sample_register_hooks(apr_pool_t *p)
{
ap_hook_handler(sample_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA sample_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 */
sample_register_hooks /* register hooks */
};
编译和安装
如果使用apxs也会很方便。使用-c进行编译,-i进行安装,-a会为httpd.conf中写入LoadModule。虽然有Makefile,可以使用make && make install,但不知为何会出错。
apxs -c -i -a mod_print.c
在httpd.conf文件中,还需要添加以下行:
<Location "/foo/">
SetHandler sample
</Location>
重启Apache并进行操作确认。
$ w3m -dump_both http://127.0.0.1/foo/
HTTP/1.1 200 OK
Date: Fri, 05 Feb 2010 22:48:00 GMT
Server: Apache/2.2.11 (FreeBSD) mod_ssl/2.2.11 OpenSSL/0.9.8e DAV/2
Content-Length: 34
Connection: close
Content-Type: text/html
The sample page from mod_sample.c
在访问控制的情况下
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
static int myauth_handler(request_rec *r)
{
if( 1 )
return OK;
else
return HTTP_FORBIDDEN;
}
static void myauth_register_hooks(apr_pool_t *p)
{
ap_hook_access_checker(myauth_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA myauth_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 */
myauth_register_hooks /* register hooks */
};
通过在if语句中进行条件判断,可以实现访问控制。然而,在这个例子中,整个网站都成为了共同的访问控制。关于仅对部分进行访问控制的方法,我将在以后进行调查。
显示各种信息 (Xianshi ge zhong xinxi)
在request_rec或request_rec.headers_in中包含了各种信息。
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
static int print_handler(request_rec *r)
{
if (strcmp(r->handler, "print")) {
return DECLINED;
}
r->content_type = "text/plain";
if (!r->header_only) {
ap_rprintf(r,"method = %s\n",r->method);
ap_rprintf(r,"uri = %s\n",r->uri);
ap_rprintf(r,"filename = %s\n",r->filename);
ap_rprintf(r,"user-agent = %s\n",apr_table_get(r->headers_in, "User-Agen
t"));
}
return OK;
}
static void print_register_hooks(apr_pool_t *p)
{
ap_hook_handler(print_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA print_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 */
print_register_hooks /* register hooks */
};
执行后会得到如下结果。
$ w3m -dump_both http://127.0.0.1/foo/
HTTP/1.1 200 OK
Date: Fri, 05 Feb 2010 22:50:40 GMT
Server: Apache/2.2.11 (FreeBSD) mod_ssl/2.2.11 OpenSSL/0.9.8e DAV/2
Content-Length: 92
Connection: close
Content-Type: text/plain
method = GET
uri = /foo/
filename = /usr/local/www/apache22/data/foo
user-agent = w3m/0.5.2
使用Cookie进行身份验证
我将之前的信息总结起来,给cookie设置了一个访问标志,并创建了一个模块,只有第一次访问时才可以访问。
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
#include <string.h>
static int cookieauth_handler(request_rec *r)
{
const char *cookie;
apr_table_set(r->headers_out, "Set-Cookie","visited=true;");
cookie = apr_table_get(r->headers_in, "Cookie");
if(cookie!=NULL && strcmp(cookie, "visited=true")==0) {
return HTTP_FORBIDDEN;
}
else {
return OK;
}
}
static void cookieauth_register_hooks(apr_pool_t *p)
{
ap_hook_access_checker(cookieauth_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA cookieauth_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 */
cookieauth_register_hooks /* register hooks */
};
出于某种原因,w3m无法正确处理Cookie,因此我尝试使用Firefox进行确认,结果只有初次加载页面才能成功显示。