2010/2/5の過去ブログの転載です。内容が古い可能性がありますのでご注意ください。
apacheのモジュールの作り方について調べてみたので、とりあえずのまとめです。
参考にしたサイト。
使用した環境は、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
のところで条件判定することでアクセス制御が出来ます。ただし、この例ではサイト全体が共通のアクセス制御になってしまいます。などで一部だけアクセス制御するための方法は、また今度調べます。
色々な情報表示
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で確認しましたが、うまく初回だけページが表示できました。