LoginSignup
16
16

More than 5 years have passed since last update.

apacheのモジュールを作ってみる

Last updated at Posted at 2015-08-04

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のところで条件判定することでアクセス制御が出来ます。ただし、この例ではサイト全体が共通のアクセス制御になってしまいます。などで一部だけアクセス制御するための方法は、また今度調べます。

色々な情報表示

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で確認しましたが、うまく初回だけページが表示できました。

16
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
16