Apache2.4 ＆ Amazon EC2 で Apacheモジュール開発


Apache `2.2` が全盛の時代に Apacheモジュールの開発をしたことがあるのですが、バージョン `2.4` になってからは触っていなかったので、自身のキャッチアップを兼ねて環境のセットアップからやってみました。

Apacheモジュールは **C言語** で、Apache から提供される **APRの関数郡** を利用しながら作るのですが、 **WEBサーバの全ての機能** にアクセスできます。
（そもそも Apache 自体が Apacheモジュールの集合体である。）

もちろんスクリプト言語的なライトさはなくコンパイル＆ビルドが必要（そのぶん **高速** ）なので、WEBのコンテンツ生成としてではなく、ミドルウェアに近い共通処理をここぞ、という場面で書くのが使いどころでしょうか。

例えば昔、DeNA さんがガラケーの絵文字変換だか何かを、Apacheモジュールで実現していたと聞いたことがあります。また、私が勤めている会社でも、[mod_ktai](http://www.yumemi.co.jp/labs_detail/id=101) というモジュールを公開していたりします。

今回は、最終的な運用では AWS で動かしたいので **Amazon EC2** で環境を構築し、ジェネレータで作成された雛型を動かすところまでやってみます。

# 前提

- サーバOSは、EC2 の Quick Start メニューにある **Amazon Linux** を利用します。
	- 現時点(2014/10/14)では次のとおり。

	![スクリーンショット 2014-10-14 17.05.53.png](https://qiita-image-store.s3.amazonaws.com/0/35733/e119a866-f5ec-9f9d-c400-fc038114ab86.png "スクリーンショット 2014-10-14 17.05.53.png")

- Apache は現時点で最新のバージョン **`2.4.10`** を適用します。
- 今回は **開発用途** を想定して Apache をインストールしているので、プロダクション(本番)ではきちんとポリシーを決めてインストールすることをお勧めします。

# Apache 2.4 のインストール

現時点では yum ではインストールできないので、wget で本体ソースを取得してコンパイルします。

> 参考：ソースのダウンロードページ ⇒ http://httpd.apache.org/download.cgi#apache24

## ① コンパイルに必要なものを事前にインストール

```shell:
$ sudo yum install -y gcc pcre-devel apr-util-devel
```

## ② Apache 2.4 のダウンロードとインストール

```shell:
$ wget http://ftp.jaist.ac.jp/pub/apache//httpd/httpd-2.4.10.tar.gz
$ gunzip -c httpd-2.4.10.tar.gz | tar xvf -
$ cd httpd-2.4.10
$ ./configure
$ make
$ sudo make install
```

## ③ 動作確認

- Apache のバージョンを確認

	```shell:
	$ /usr/local/apache2/bin/httpd -v
	
	Server version: Apache/2.4.10 (Unix)
	Server built:   Oct 14 2014 07:53:06
	```

	> 実際には、パスを通しておくと楽だと思います。

- Apache の起動

	```shell:
	$ sudo /usr/local/apache2/bin/httpd -k start
	```

	> 初期状態では次のようになっています。
	> 
	> - 設定ファイルの場所：/usr/local/apache2/conf/httpd.conf
	> - ドキュメントルート：/usr/local/apache2/htdocs
	> - apxsコマンドのパス：/usr/local/apache2/bin/apxs

- ブラウザでEC2の `Public IP` へアクセスします。
	- AWSのセキュリティグループの設定で HTTPの80番ポートを開けておく必要があります。

		![screen.png](https://qiita-image-store.s3.amazonaws.com/0/35733/41381759-96cc-ba61-848a-00e85df3e2aa.png "screen.png")

# Apache モジュールの作成

今回は動作確認を兼ねて、雛型をそのまま動かしてみます。

> 参考：http://httpd.apache.org/docs/2.4/programs/apxs.html

## ① 雛型の生成

```shell:
$ /usr/local/apache2/bin/apxs -g -n hoge
```

> `-g`: 雛型の generate です。
> `-n`: モジュールの name です。

すると次のようにファイルが展開されます。

![screen1.png](https://qiita-image-store.s3.amazonaws.com/0/35733/c4d92bb7-13fd-593a-45c2-41b6a045963b.png "screen1.png")

ちなみにこの雛型は **コンテンツハンドラー** 、つまり PHP 等のスクリプトと同じく、クライアントへ返すコンテンツを生成する Apache のフェーズにフックしています。

```c:hoge/mod_hoge.c
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"


/* The sample content handler */
static int hoge_handler(request_rec *r)
{
    if (strcmp(r->handler, "hoge")) {
        return DECLINED;
    }
    r->content_type = "text/html";      

    if (!r->header_only)
        ap_rputs("The sample page from mod_hoge.c\n", r);
    return OK;
}

static void hoge_register_hooks(apr_pool_t *p)
{
    ap_hook_handler(hoge_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA hoge_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       */
    hoge_register_hooks  /* register hooks                      */
};
```

## ② コンパイル＆インストール

- コンパイル

	```shell:
	$ cd hoge
	$ /usr/local/apache2/bin/apxs -c mod_hoge.c
	```

	> `-c`: compile です。

- インストール

	```shell:
	$ cd hoge
	$ sudo /usr/local/apache2/bin/apxs -i -a mod_hoge.la
	```

	> `-i`: install です。
	> `-a`: httpd.conf に自動で設定が add されます。

	すると `/usr/local/apache2/modules/` 配下にモジュールが配置され、

	![screen2.png](https://qiita-image-store.s3.amazonaws.com/0/35733/e3725933-5f23-5396-8b97-439628ce0bde.png "screen2.png")

	httpd.conf に自動でモジュール読み込みの記載が追記されます。

	```apacheconf:/usr/local/apache2/conf/httpd.conf
	LoadModule hoge_module        modules/mod_hoge.so
	```

## ③ 動作確認

この雛型はコンテンツハンドラーなので、`http://<ドメイン>/hoge` にアクセスしたらハンドラーを起動するようにします。

- `httpd.conf` へ追記します。

	```apacheconf:/usr/local/apache2/conf/httpd.conf
	<Location /hoge>
	  SetHandler hoge
	</Location>
	```

- `httpd.conf` のシンタックスに間違いがないかチェックします。

	```shell:
	$ /usr/local/apache2/bin/httpd -t
	
	Syntax OK
	```

- Apacheを再起動します。

	```shell:
	$ sudo /usr/local/apache2/bin/httpd -k graceful
	```

	> `restart` でもいいのですが、`graceful` で再起動すると、Apacheの(子)プロセスがアクセス中のリクエストを裁いてから再起動となります。

- ブラウザで `/hoge` にアクセスします。次のように表示されればOKです。

	![54_68_221_199_hoge.png](https://qiita-image-store.s3.amazonaws.com/0/35733/1721d2fb-66d2-6cfb-5eba-fbe3f663b7c3.png "54_68_221_199_hoge.png")

# おわりに

今回は、ハンドラーとして簡単な例を説明しました。たぶん今の『スマホ時代』で作ると良いなあと個人的に思うのは、次のようなものです。

- フィルター機能を使ってコンテンツ変換
	- 例えば PHP や Rails等 での レスポンスbody を変換する
	- 用途は **多デバイスへの対応**
- **APIサーバ** としての共通処理
	- 認証やキャッシュ
	- フォーマット変換
- 他にも **高速化** が求められる処理

また最近は **mod_mruby** を使えば、Ruby で Apacheモジュールを書けるようですので、こちらにもチャレンジしてみようかなと。
（Apache `2.2` ですが、EC2に導入する手順は以前に書きました ⇒ [mod_mruby を Amazon EC2 へ導入する](http://qiita.com/hkusu/items/09d0515c80206d264bee)）