手軽に出来るApacheモジュール開発

こんにちは、アシアルの井川です。

今日はApacheモジュール開発方法を紹介したいと思います。難しそうに聞こえるかもしれませんが、Apacheのツール(apxs)を使うので意外と簡単に作成できます。また、今回作成するのは"hello world"をHTMLの先頭に加えるだけのシンプルなモジュールです。

本当に簡単なので、ぜひ一度作ってみて下さい。

開発の流れは次の通りです。

0. 開発環境の準備
1. モジュールのひな形の作成
2. コードの記述(C言語)
3. コンパイルしてインストール
4. httpdの再起動

開発環境は既にできている前提で話を進めます。必要なパッケージは

・httpd
・httpd-devel
・gcc

であり、検証環境は次の通りです。

・CentOS 5.5
・Apache 2.2.3

ただし、httpdにso_moduleが組み込まれている必要があります。次のコマンドを実行し、実行結果に"mod_so.c"が入っていれば大丈夫です。


> /usr/sbin/httpd -l


[実行結果例]
core.c
prefork.c
http_core.c
mod_so.c

① モジュールのひな形作成

まずは、apxsを使ってひな形を作りましょう。適当なディレクトリに移動して、次のコマンドを実行します。


> /usr/sbin/apxs -g -n hello_world
(-g:テンプレート生成、-n:モジュール名指定)


[実行結果]
Creating [DIR]  hello_world
Creating [FILE] hello_world/Makefile
Creating [FILE] hello_world/modules.mk
Creating [FILE] hello_world/mod_hello_world.c
Creating [FILE] hello_world/.deps

これでhello_worldディレクトリが作成されました。そのディレクトリへ移動します。

② コードの記述(C言語)

次に、生成されたソースコード(mod_hello_world.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 hello_world_handler(request_rec *r)
  8. {
  9. if (strcmp(r->handler, "hello_world")) {
  10. return DECLINED;
  11. }
  12. r->content_type = "text/html";
  13.  
  14. if (!r->header_only)
  15. ap_rputs("The sample page from mod_hello_world.c\n", r);
  16. return OK;
  17. }
  18.  
  19. static void hello_world_register_hooks(apr_pool_t *p)
  20. {
  21. ap_hook_handler(hello_world_handler, NULL, NULL, APR_HOOK_MIDDLE);
  22. }
  23.  
  24. /* Dispatch list for API hooks */
  25. module AP_MODULE_DECLARE_DATA hello_world_module = {
  26. STANDARD20_MODULE_STUFF,
  27. NULL, /* create per-dir config structures */
  28. NULL, /* merge per-dir config structures */
  29. NULL, /* create per-server config structures */
  30. NULL, /* merge per-server config structures */
  31. NULL, /* table of config file commands */
  32. hello_world_register_hooks /* register hooks */
  33. };
  34.  
  35.  

関数の役割は次の通りです。


hello_world_handler:実際の処理をするハンドラ
hello_world_register_hooks:ハンドラをフックポイントに登録する関数

今回はHTMLファイルに"hello_world"を追加したいので、hello_world_handlerを次のように修正します。

  • static int hello_world_handler(request_rec *r)
  • {
  • if (!strcmp(r->content_type, "text/html") && !r->header_only) {
  • ap_rputs("hello world<br />\n", r);
  • }
  •  
  • return DECLINED;
  • }

ここで、request_recはHTTPリクエストを表した構造体です。r->content_typeはContent-Typeヘッダであり、r->header_onlyはHEADリクエストか否かを示します。また、ap_rputs()はコンテンツを出力する関数です。ハンドラの戻り値にも意味があり、DECLINEDを返すと、Apacheは次のモジュールに処理を委譲します。

つまり、上記のコードでは、Content-Typeがtext/htmlで、HEADリクエストでない場合、"hello world"を追加して、Apacheの処理を続行します。

③ コンパイルしてインストール

では、さっそくコンパイルしてインストールしてみましょう(root権限もしくはsudoで実行)。


[コンパイルとインストールを同時に実行]
> /usr/sbin/apxs -i -a -c mod_hello_world.c
 &nbsp;
[別々に実行]
コンパイル  > /usr/sbin/apxs -c mod_hello_world.c
インストール> /usr/sbin/apxs -i -a -n 'hello_world' mod_hello_world.la
 &nbsp;
 &nbsp;
(インストールが終わったら、make cleanしておく)

インストール後にhttpd.confを確認すると、


LoadModule hello_world_module  /usr/lib/httpd/modules/mod_hello_world.so

という一文が追加されていると思います(なかったら追加して下さい)。これで準備は完了です。

④ httpdの再起動

Apacheを再起動します。


> /sbin/service httpd restart

ブラウザでサーバ内の適当なファイルへアクセスして下さい。先頭に"hello world"の一文がついているでしょうか?

と、こんな感じで作成できます。

これだけだとメリットが見えませんが、C言語による処理ですので非常に高速に動作するため、DBやmemcachedとの通信を加えると、大量のリクエストを高速に処理することも可能です。

ぜひ、一度試し、次のステップへとつなげて下さい。