HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

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

> 

Cコンパイラなどは「C:\Perl\site」の下に導入されるらしい。

Apache httpdの導入

Apacheモジュールの開発に当たっては、ヘッダファイルやライブラリファイルが必要になる。
今回は、Apache 2.2.16(httpd-2.2.16-win32-x86-openssl-0.9.8o.msi)を使用する。
Apache httpdインストーラを使って導入する場合、次の手順で導入する。*1 *2

  1. インストーラを起動し、ライセンスの確認などを進める。
  2. Setup Type 画面で Custom を選択し、Custom Setup 画面で「Build Headers and Libraries」をインストールするように変更する。
  3. 後は指示通りに進めてインストールする。

これによってインストールされるのが、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++)のコードを書いたらしい。

*1:既にインストールされている場合は、コントロールパネルのアプリケーションの変更とかで追加できるのかなぁ。未確認。

*2:自分の環境ではちょっと強引なことをやっていて、Apache httpdはインストールされていないことになっているが、稼動はしている、という状態なので、新規インストールして必要なファイルをコピーした。