Windows環境でApacheモジュールを開発してみる
ふと、作りたいものができたので、まずは環境構築から、ということで、ざっと調べてみたところ、次のサイトを見つけた。
基本的に、apxsを使うということでよいので、と思ったら、Windows環境ではPerl実行環境を入れるところから始めなきゃならないらしい。なので、もう最初からすべての手順を並べてみることにしたらしい。
Perl実行環境の導入
後述するapxsツールの導入および実行のために必要なので仕方がない(謎)。
Perl実行環境として、ActivePerlを使用する。
今回ダウンロードしたのはActivePerl-5.12.3.1204-MSWin32-x86-294330.msi。
これを実行して、適当なところにインストールする。.plファイルへの関連付けはなしにした(邪魔くさいので(謎))。
今回、インストール先は「C:\Perl」とする。
Cコンパイラ等の導入
同じく後述するapxsツールの導入等に必要。
既存のMinGW環境があればそれを使ってもよいが、自分の場合、dmakeがないと言われるので、別途導入する方を選んだ。
コマンドプロンプトで以下のコマンドを実行する。
> SET PATH=C:\Perl\bin;C:\Perl\site\bin;%PATH% > ppm install MinGW Downloading ActiveState Package Repository packlist...done Updating ActiveState Package Repository database...done Syncing site PPM database with .packlists...done Downloading MinGW-5.1.4.1...done Downloading dmake-4.11.20080107...done Unpacking MinGW-5.1.4.1...done Unpacking dmake-4.11.20080107...done Generating HTML for MinGW-5.1.4.1...done Generating HTML for dmake-4.11.20080107...done Updating files in site area...done 1070 files installed >
Apache httpdの導入
Apacheモジュールの開発に当たっては、ヘッダファイルやライブラリファイルが必要になる。
今回は、Apache 2.2.16(httpd-2.2.16-win32-x86-openssl-0.9.8o.msi)を使用する。
Apache httpdをインストーラを使って導入する場合、次の手順で導入する。*1 *2
- インストーラを起動し、ライセンスの確認などを進める。
- Setup Type 画面で Custom を選択し、Custom Setup 画面で「Build Headers and Libraries」をインストールするように変更する。
- 後は指示通りに進めてインストールする。
これによってインストールされるのが、includeディレクトリとlibディレクトリ。
なお、Apache httpdは「C:\Apache2.2」にインストールされているものとする。
apxsの導入
上記の手順を経て、ようやくここまでたどり着く。
まずは、以下のサイトから「apxs_win32.zip」をダウンロード。
ダウンロードしたファイルを適当な場所に解凍する。今回は「C:\apxs」以下に展開したものとする。
続いて、以下のコマンドを実行する。(詳しくは、apxsのREADMEを参照)
> SET PATH=C:\Perl\bin;C:\Perl\site\bin;%PATH% > CD /D C:\apxs > perl Configure.pl --with-apache2=C:\Apache2.2 --with-apache-prog=httpd.exe Set up gcc environment - 3.4.5 (mingw-vista special r3) apxs.bat has been created under C:\Apache2.2\bin. apr-1-config.pl.bat has been created under C:\Apache2.2\bin. apu-1-config.pl.bat has been created under C:\Apache2.2\bin. >
何かを動かしてみる
まずは、「Hello World」でもしますか、ということで(謎)、サンプルをそのまま動かしてみる。
まずは、以下のコマンドを実行。(PATHの設定は、さっきの続きでやっているなら「C:\Apache2.2\bin」を追加すればよい)
> set PATH=C:\Apache2.2\bin;C:\Perl\bin;C:\Perl\site\bin;%PATH% > apxs -g -n hello_world Use of assignment to $[ is deprecated at C:\Apache2.2\bin/apxs.bat line 120. Creating [DIR] hello_world Creating [FILE] hello_world/Makefile Creating [FILE] hello_world/mod_hello_world.c Creating [FILE] hello_world/.deps >
(Perlの警告(かな?)が出ているが、とりあえず気にしないことにする)
まずは、この生成されたサンプルをそのまま実行してみる。ということで、モジュールのコンパイルとインストール。今回は、コンパイルとインストールを別コマンドで実行してみる。まずはコンパイル。
> CD hello_world > apxs -c mod_hello_world.c Use of assignment to $[ is deprecated at C:\Apache2.2\bin/apxs.bat line 120. C:/Perl/site/bin/gcc.exe /nologo /MD /W3 /O2 /D WIN32 /D _WINDOWS /D NDEBUG -I"C:\Apache2.2\include" /c /Fomod_hello_world.lo mod_hello_world.c gcc.exe: /nologo: No such file or directory gcc.exe: /MD: No such file or directory gcc.exe: /W3: No such file or directory gcc.exe: /O2: No such file or directory gcc.exe: /D: No such file or directory gcc.exe: WIN32: No such file or directory gcc.exe: /D: No such file or directory gcc.exe: _WINDOWS: No such file or directory gcc.exe: /D: No such file or directory gcc.exe: NDEBUG: No such file or directory gcc.exe: /c: No such file or directory gcc.exe: /Fomod_hello_world.lo: No such file or directory apxs:Error: Command failed with rc=65536 . >
おっと、ここで、スラッシュで始まる文字列をファイルのフルパスだと解釈してしまうMinGW環境での問題。っていうか、gccに渡しているオプションが明らかにVCのオプションになっている。そりゃだめだろ‥orz
ってことで、ここからは自力でコンパイルモード(何)。要は、Windowsのダイナミックリンクライブラリができればいいわけで。
以下の記事を参考に、オプション等を指定。
> g++ -mwindows -I C:\Apache2.2\include -L C:\Apache2.2\lib -c mod_hello_world.c > g++ -mwindows -I C:\Apache2.2\include -L C:\Apache2.2\lib -shared -o mod_hello_world.so mod_hello_world.o -llibhttpd >
そしてインストール。
> copy mod_hello_world.so C:\Apache2.2\modules 1 個のファイルをコピーしました。 >
設定。とりあえず、httpd.confに以下の各設定を追加。
LoadModule hello_world_module modules/mod_hello_world.so
<Location /hello_world> Order allow,deny Allow from all SetHandler hello_world </Location>
で、Apache httpdを再起動して、次のようなURLにアクセス。
これで、次のような文字列が画面に表示されればOK。
The sample page from mod_hello_world.c
アクセス制限のための簡易フィルタを作ってみる
冒頭に挙げたサイトにあるサンプルも参考にしながら、簡単なアクセス制限フィルタを作ってみることにする。
お試しなので、仕様は単純にする。
- URLパラメータに「allow=true」というのが含まれていたら、"OK"という文字列を出力する
- それ以外の場合には、HTTPステータスコード403を返す
hello_worldモジュールと同様に、こんどはsimple_filterモジュールを生成する。
生成されたソース「mod_simple_filter.c」を次のように修正する(抜粋)。
//(前略) #include "httpd.h" #include "http_config.h" #include "http_protocol.h" #include "ap_config.h" #include "apr_strings.h" /* The sample content handler */ static int simple_filter_handler(request_rec *r) { if (r->args) { char* rest; char* param = apr_strtok(r->args, "&", &rest); for (;param; param = apr_strtok(NULL, "&", &rest)) { if (!strcmp(param, "allow=true")) { return DECLINED; } } } r->status = HTTP_FORBIDDEN; return OK; } //(後略)
GETパラメータの解析処理は、次のサイトを参考に実装。
同様にコンパイル。ただし、apr_strtok関数を使う関係で、libapr-1 をリンクしないといけない。
> g++ -mwindows -I C:\Apache2.2\include -L C:\Apache2.2\lib -c mod_simple_filter.c > g++ -mwindows -I C:\Apache2.2\include -L C:\Apache2.2\lib -shared -o mod_simple_filter.so mod_simple_filter.o -llibhttpd -llibapr-1 >
そしてインストール。今回は、httpd.confへの追加は以下のみ。
LoadModule simple_filter_module modules/mod_simple_filter.so
動作検証だが、curlコマンドが利用可能ならヘッダの内容から結果が分かりやすい。
> curl -i 'http://localhost/samples/apxs/hello_world/hoge.txt' HTTP/1.1 403 Forbidden (略) > curl -i 'http://localhost/samples/apxs/hello_world/hoge.txt?allow=false' HTTP/1.1 403 Forbidden (略) > curl -i 'http://localhost/samples/apxs/hello_world/hoge.txt?allow=true' HTTP/1.1 200 OK (中略) This is a text file named "hoge.txt" > curl -i 'http://localhost/samples/apxs/hello_world/hoge.txt?hoge=foo&allow=true' HTTP/1.1 200 OK (中略) This is a text file named "hoge.txt" >
とりあえず、今日はここまで。
あとやりたいのは‥
- ヘッダの内容に基づくフィルタリング
- httpd.confでmod_simple_filterに関する何かの設定
結局、サンプルのソースコードが手に入ってしまったら、MinGW/MSYS環境がありさえすれば、最初にインストールしたActivePerlとかもう要らないんじゃ‥
しかし、ちょっとではあるが、久しぶりにC言語(実はg++でコンパイルしているので、構文規則はC++)のコードを書いたらしい。