2006年07月12日

apache module 開発事始め

はてなブックマークに登録


先日は,必要に迫られて Apache 1.3 の mod_access を改造したというを書きました.その時は単にあるものを改造しただけでしたが,ふと思い立って,一から Apache 2.0 用のモジュールを書いてみました.書く上で色々 Web サイトを探してみたのですが,あまり日本語の入門向けの文章が見あたらなかったので,開発する上で分かったこと(と言うほど大したものじゃないですが)をまとめておこうと思います.


Apache は,リクエストを処理する上で細かくフェーズを設定して,その各フェーズで様々な処理を行います.Apache のモジュールの開発は,そのモジュールが目的の処理をする上で適切なフェーズに Apache の処理が至ったときに,Apache から呼び出してもらうための関数(hook 関数)を作ることと,そのモジュールが動作するための設定を行う関数を作ること,になります.


フェーズには,例えばそのリクエストを受け付けるか拒否するかを決めるフェーズや,リクエストされた URI と実際のディスク上のファイルとの間の対応付けを解決するフェーズ,そしてもちろん実際のレスポンスを生成するフェーズ等があります.hook 関数を挿入するポイントはこれらのフェーズになりますが,もちろんその全てのフェーズのための関数を用意する必要はありません.また個別の設定を施す必要がなければ,設定用の関数も定義する必要ありません.なので,もっとも小規模なモジュールでは,hook 関数を一つと,hook 関数を Apacheに登録するための関数が必要ですからもう一つ,都合二つの関数を定義すれば済みます.Apache の標準モジュールである mod_asis モジュールも,そのような関数が二つだけ定義されたモジュールです.


さて,モジュール開発の始め方ですが,Apache をインストールした時に一緒にインストールされている,apxs コマンドを使います.以下の話は全て Linux 上で実行した場合の話です.このコマンドは Apache のモジュール開発を取り仕切るコマンドで,新しいモジュールを作る時のソースファイルのテンプレートを出力してくれたり,モジュールをコンパイルしてくれたりする,とても便利なものです.
テンプレートを出力するには

 apxs -g -n test

とします.-g がテンプレート出力コマンドで -n オプションでそのモジュールの名前を指定します.すると,カレントディレクトリに test という名前のディレクトリが作成されて,
 Makefile  mod_test.c  modules.mk

の3つのファイルが作成されます.modules.mkMakefile のサポート用のファイルです.mod_test.c がモジュールのソースファイルになります.基本的には,このファイルを編集して,必要な hook や設定用の関数を定義していくことになります.
mod_test.c の中身は,次のようになっています(頭のコメントは省いています).
  1  #include "httpd.h"
2 #include "http_config.h"
3 #include "http_protocol.h"
4 #include "ap_config.h"
5
6 /* The sample content handler */
7 static int test_handler(request_rec *r)
8 {
9 if (strcmp(r->handler, "test")) {
10 return DECLINED;
11 }
12
13 r->content_type = "text/html";
14 if (!r->header_only)
15 ap_rputs("The sample page from mod_test.c\n", r);
16
17 return OK;
18 }
19
20 static void test_register_hooks(apr_pool_t *p)
21 {
22 ap_hook_handler(test_handler, NULL, NULL, APR_HOOK_MIDDLE);
23 }
24
25 /* Dispatch list for API hooks */
26 module AP_MODULE_DECLARE_DATA test_module = {
27 STANDARD20_MODULE_STUFF,
28 NULL, /* create per-dir config structures */
29 NULL, /* merge per-dir config structures */
30 NULL, /* create per-server config structures */
31 NULL, /* merge per-server config structures */
32 NULL, /* table of config file commands */
33 test_register_hooks /* register hooks */
34 };

このコードの要素を軽く解説すると,test_handler() 関数はリクエストに対するレスポンスデータを生成するハンドラー関数です.このハンドラーの呼び出しは後述します.test_register_hooks() はこのモジュールで定義した hookを Apache に登録するための関数です.Apache の初期化時に呼び出されます.この中で呼び出している ap_hook_handler() 関数は,名前の通り handler を登録するためのものです.登録する hook の種類毎にこのような関数が用意されています.test_module 配列は,前述の hook 登録関数や(ここでは定義されてませんが)ディレクティブを処理する関数群を Apache に渡すためのものです.詳しくは別の稿で書こうと思います.


これをコンパイルするには,mod_test.c と一緒に生成された Makefile を使って make するか,apxs コマンドを使います.
make する場合は,単に make すればコンパイルできます. install ターゲットを指定すれば,コンパイルが成功したら続けて,できあがった DSO ファイルを modules ディレクトリにコピーしてくれます.
apxs コマンドを使う場合は,

 apxs -c mod_test.c

でコンパイルできます.コンパイルと同時に modules ディレクトリにコピーするには
 apxs -c -i mod_test.c 

とします.更に -a オプションを指定しておけば,httpd.conf ファイルにこのモジュールを読み込む設定(LoadModule ディレクティブ)を追加してくれます.
 apxs -c -i -a mod_test.c 

実際にこのモジュールを使うには,例えば次のような設定を httpd.conf の適当なところに追加します.
 <Location "/hoge/">
SetHandler test
</Location>

設定を追加して Apache を(再)起動したら,http://localhost/hoge/ をリクエストしてみます(ホスト名やポート番号は,実際の設定に合わせてください).すると次のようなレスポンスが返ってきます.
 The sample page from mod_test.c

これは,上記のコードの 15行目で書き出したものです.


さて,このリクエストに先程コンパイルしたモジュールを結びつけているのが,httpd.conf に追加した

 <Location "/hoge/">
SetHandler test
</Location>

の設定です.つまり,/hoge/ で始まる URI がリクエストされれば,そのリクエストを処理するハンドラとして test を使うことを指定します.
クライアントからリクエストがあると test_handler() がリクエストの度に呼び出されます.test_handler() は呼び出されると自分がそのリクエストを処理するべきか調べます(コードの 9行目).自分が処理するべきならば,r->handler の値が test になっています(この値を設定するのが SetHandler ディレクティブの仕事です).自分が処理するべきリクエストなら,レスポンスデータを生成(15行目)します.


如何でしょうか.意外と簡単じゃないですか? 今回はさわりだけでしたが,稿を改めて他のフェーズでの処理の話や実際にモジュールを書く上で便利なライブラリの話などを書いてみたいと思います.


参考文献:

klab_gijutsu2 at 22:52│Comments(6)TrackBack(1)apache | 開発

トラックバックURL

この記事へのトラックバック

1. 日記/2008-02-19  [ Naruのメモサイト (PukiWiki/TrackBack 0.4) ]   2008年02月19日 04:26
Apacheのモジュール作成 ひな形の作成 http://d.hatena.ne.jp/s-masatarou/20070502/1178130657 上記サイトでの修正 LoadModule testworld_module xxx/mod_testmodule.so &lt;Location /hello&gt; SetHandler testworld &lt;/Location&gt; 参考リンク http...

この記事へのコメント

1. Posted by masa   2006年07月14日 15:52
4 こんにちは、

apxsでモジュールのテンプレートを作れるなんて知りませんでした。
自分で書いてもさほど手間がかかるテンプレートではないですが、これがあるだけで敷居はぐっと低く感じられますね。
2. Posted by nakano   2006年09月28日 10:58
5 今後も期待しています。
4. Posted by perisy   2007年08月23日 10:25
5 参考にさせていただいてます。

mod_test.cのコードで「>」が「>gt;」と表示されているようなので報告いたします。
5. Posted by かつみ   2007年08月23日 11:04
ご報告ありがとうございます.修正しておきました.
6. Posted by nao   2007年08月23日 14:26
5 この手のwebでの資料は少ないので、
本当に参考になります。
これからも記載宜しくお願いいたします。
7. Posted by ariari   2007年09月13日 21:42
5 こういったHotToが公開されることで、ぐっと敷居が低くなりますね。
勉強になりました。

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント