とはいえ、何日も更新が無いというのはなんとかしたいものです。
そこで、DによるWebアプリ実装についての記事を
細かく刻んで小出しし、乗り切ってみたいと思います。
ちなみに何故Webアプリかと言うと、
何回か実装していてわりと内容がまとまっているからです。
(実はこのブログもDによるWebアプリの実装になっています。)
この記事ではシンプルな掲示板の作成を目指したいと思います。
一口にWebアプリといっても色々と実装方法がありますが、
今回はFastCGIを使用して実装します。
それと、FastCGI用の自家製フレームワークがありますので併せて使用します。
FastCGIを選んだのは、せっかくDで書くなら実行速度が速いといいなぁという理由です。
環境構築
FastCGIを使いますので、次の2つが必要になります。- FastCGIライブラリ
- FastCGI実行環境
また、Dを使いますのでdmdも必要です。
環境構築方法は話の本筋ではありませんが、
「Hello work!!」出すだけだと内容が薄いので、
CentOS 6.0(x64)上に構築する場合を例として簡単に書いておきます。
開発環境として、手間がかからず動けば良いという観点の方法ですので、
実際に構築する場合は色々調整してください。
FastCGIライブラリのインストール
CentOS 6.0のMinimalインストールは本当にMinimalだったのでビルドツール等を色々入れます。
# yum -y install gcc # yum -y install make # yum -y install patch # yum -y install wget
FastCGIサイトからソースをダウンロードして解凍します。
# wget http://www.fastcgi.com/dist/fcgi.tar.gz # tar xzvf fcgi-2.4.0.tar.gz
GCCのバージョンアップのためかと思いますが、
EOFマクロがエラーを出すようなので、パッチを当てます。
(stdio.hのincludeを足すだけです。)
# cd fcgi-2.4.0/libfcgi/ # patch -p0 < ../../fcgi-2.4.0-gcc4.patch
パッチの内容は次の通りです。
--- fcgio_old.cpp 2002-02-25 05:12:22.000000000 +0900 +++ fcgio.cpp 2011-10-21 16:26:18.039072131 +0900 @@ -22,6 +22,7 @@ #define DLLAPI __declspec(dllexport) #endif +#include <stdio.h> #include <limits.h> #include "fcgio.h"
後はビルドしてインストールします
# cd .. # ./configure # make # make check # make install
FastCGI実行環境のインストール
WebサーバはApacheを使います# yum -y install httpd
mod_fcgidのビルドのためにApache開発環境をインストール
# yum -y install httpd-devel
mod_fcgidをダウンロードして解凍
# wget http://ftp.jaist.ac.jp/pub/apache//httpd/mod_fcgid/mod_fcgid-2.3.6.tar.gz # tar xzvf mod_fcgid-2.3.6.tar.gz
mod_fcgidをビルドしてインストール
# cd mod_fcgid-2.3.6 # ./configure.apxs # make # make install
dmdのインストール
unzipも無ければ入れないといけません。# yum -y install unzip
dmdのダウンロードと解凍と配置
# wget http://ftp.digitalmars.com/dmd.2.055.zip # unzip dmd.2.055.zip # mv dmd2 /usr/local/
dmdにシンボリックリンクを張る
# cd /usr/local/bin/ # ln -s /usr/local/dmd2/linux/bin64/dmd
設定ファイルを設置
# cp /usr/local/dmd2/linux/bin64/dmd.conf /etc/
設定ファイルはフルパスで書く派です
[Environment] DFLAGS=-I/usr/local/dmd2/src/phobos -I/usr/local/dmd2/src/druntime/import -L-L/usr/local/dmd2/linux/lib64 -L-L/usr/local/dmd2/linux/lib32 -L--no-warn-search-mismatch -L--export-dynamic -L-lrt
アプリケーションのビルド
アプリケーションのソースをダウンロードし、dmdでビルドします# dmd @switches
出来た実行ファイルを設置します
# mkdir /var/www/fcgi-bin/ # mv bbs.fcgi /var/www/fcgi-bin/
Apacheの設定
mod_fcgidの設定を追加します。FcgidProcessTableFile /var/run/fcgid_shm FcgidIPCDir /tmp/fcgid_sock/ FcgidMaxProcessesPerClass 1
その他オプションについてはmod_fcgid公式を参照してください。
fcgiファイルを置くディレクトリの設定を追加します。
<Directory "/var/www/fcgi-bin/"> AllowOverride None Options +ExecCGI Order allow,deny Allow from all SetHandler fcgid-script </Directory>
/bbs/以下のアクセスが作成したfcgiファイルに行くよう設定します。
RewriteEngine on RewriteRule ^/bbs/.*$ /var/www/fcgi-bin/bbs.fcgi [L]
Apacheの起動
mod_fcgidはSELinuxに弾かれるようなのでSELinuxは切ります。# echo 0 > /selinux/enforce
また、CentOSのデフォルトiptablesは80ポートが塞がっているのでとりあえずクリアします。
# iptables -F
そうしましたらApacheを起動します。
# service httpd start
動作確認
該当URLにアクセスします。http://hostname/bbs/ThreadList.html
Hello work!!と表示されれば成功です。
ソースについて
modules以下にライブラリが入っていますが、これの内容ついては細かく触れません。使うだけです。アプリケーションのソースはsources以下にあります。
エントリポイントはjp.ku6.bbs.mainモジュールにあります。
記述量はそれほど無く、コメントも入れているのでなんとなく内容はわかるかと思います。
1 | void main(string[] arguments) |
---|---|
2 | { |
3 | // フレームワークオブジェクトの生成 |
4 | auto raptan = new Raptan(8192, 8192, "/tmp"); |
5 | |
6 | // 拡張子を判断して自動でContent-Typeを出力する設定 |
7 | auto contentTypeFilter = new ContentTypeFilter; |
8 | contentTypeFilter.add("html", "text/html; charset=UTF-8"); |
9 | raptan.addFilter(contentTypeFilter); |
10 | |
11 | // リクエストメソッドフィルタリング設定 |
12 | raptan.addFilter(new RequestMethodFilter(Request.Method.GET | Request.Method.POST)); |
13 | |
14 | // パスに対して処理を設定 |
15 | auto threadListAction = new ThreadListAction; |
16 | raptan.setAction(APPLICATION_ROOT_URI ~ "/ThreadList.html", &threadListAction.execute); |
17 | |
18 | // リクエストの受付を開始 |
19 | raptan.start(); |
20 | |
21 | // アプリケーションの終了を待機 |
22 | raptan.join(); |
23 | } |
ポイントとしては、jp.ku6.raptan.core.RaptanがFastCGI用のフレームワークになっています。
RaptanオブジェクトにURLのパスと処理内容のdelegateをセットで登録すると、
そのURLにアクセスしたときに対応するdelegateが呼び出されます。
1 | // パスに対して処理を設定 |
---|---|
2 | auto threadListAction = new ThreadListAction; |
3 | raptan.setAction(APPLICATION_ROOT_URI ~ "/ThreadList.html", &threadListAction.execute); |
セットしている処理内容はjp.ku6.bbs.action.ThreadListActionにあります。
HTTP Responseオブジェクトに対してHTMLデータを出力しています。
1 | string execute(Request request, Response response) |
---|---|
2 | { |
3 | // まずはHTMLテキストを出力するだけ |
4 | response.append("<html><head><title>Hello work!!</title><body>Hello work!!</body></html>"); |
5 | return null; |
6 | } |
次回へ続く。