Mojoを使って自作ウェブアプリをよりポータブルに!

第1回じめてのMojo

2009年12月8日:サンプルコードを現在のバージョンで動作するよう修正しました。

mod_perlの教訓

一昔前まで、Perlである程度大規模なウェブアプリケーションを書くときはmod_perlと呼ばれるApacheモジュールを利用するのが一般的でした。

ところが、Apache、mod_perlともに大規模な改修が行われ、後方互換性が失われた結果、古いmod_perlのアプリケーションを抱えている企業は、リスクや不便を覚悟で古いApacheを使い続けるか、Apache、mod_perlともに新しい環境に移行するか、あるいはまったく異なる第三の道を模索するかの選択を迫られることになりました。

同じようなことは、もっと小規模なアプリケーションでも起こりえます。たとえば、昔ながらのCGI環境で実行していたものをもっと高速な環境に移行したくなったとき。たしかにmod_perlにはApache::PerlRunと呼ばれる互換モードもありますが、これまではアプリケーションそのものを書き直すのが常でした。

サーバをとるか、フレームワークをとるか

もちろんよくできたフレームワークを使えば、このような差違は吸収できます。

たとえば海外でよく利用されているHTML::Masonは、1998年の登場時点ですでにmod_perlとCGI環境の双方に対応していましたし、mod_perlの書き直しが始まった2002年にはCVS上の開発版を利用して将来の変化に備えていました。

ただし、これはあくまでもHTML::Mason内部での対応にすぎません。HTML::MasonはPHPなどと同じくテンプレート内部にコードを埋め込むタイプのテンプレートエンジンを採用していますから、異なるテンプレートエンジンを利用していた企業にとっては、サーバ環境の移行に引けをとらないコストがかかってしまいます。⁠Apache2やめますか、Template-Toolkitやめますか」という選択は健全とはいえません。

Mojoはサーバとフレームワークをつなぐミドルウェア

Mojoは、そのような問題を解決するために生まれました。その歴史については連載の第4回でまたあらためて説明しますが、ここでは自社のアプリケーションないしフレームワークをMojoの規約に対応させれば、CGIやFastCGI、mod_perlといった環境にシームレスに対応できるようになる――だけでなく、開発用のスタンドアロンサーバなどもついてくる――ということを覚えておいていただければ結構です。

「規約に対応させる」というと、なにか大変な作業が必要になるような印象を受けるかもしれませんが、Mojoが取り扱うのはあくまでアプリケーション本体とサーバをつなぐ部分のみ。だから、基本的には、サーバから送られてくるクエリストリングやフォームデータの解析とヘッダやボディをサーバに送り返す処理を、アプリケーションの内部ではなく、Mojoにさせるように書き換えるだけのことです。

と、いくら言葉で説明してもわかりづらいと思いますので、まずは実際にMojoをインストールして、簡単なアプリケーションを作成してみましょう。

インストールはとても簡単

Perlのモジュールというと、インストールが大変という印象があるかもしれません。

言葉で書けばシェルから「cpan <モジュール名>するだけなのですが、なかには芋づる式に何十個ものモジュールがインストールされたり、C言語の開発環境が必須というものがあったりで、最近の有名で高性能なモジュールになればなるほど、ある程度融通が利く環境にしか入れられないようになっています。

でも、アプリケーションをサーバ環境の制約から解放するのが目的のミドルウェアとしては、そのような取り扱いのむずかしさは害でしかありません。

だから、Mojoは、その思想的な祖先であるWSGI(Web Server Gateway Interface)※1の理念にしたがって、不要な依存関係はいっさい省き、なるべく簡単にインストールできるようにつくられています。

2009年1月の時点では、テストにしか使わないものを含めてちょうど20個の依存モジュールが列挙されていますが、そのすべてがPerl 5.8.8(2006年1月リリース)以降標準添付されているもの。本体だけであれば2002年7月リリースのPerl 5.8.0でも問題なく動作します。

githubからのインストール

いつものようにCPANからインストールしてもそれほどの手間にはならないのですが、ここでは将来的にアプリケーションを別の環境に移動するときの便を考えて、githubから開発版をダウンロードしてくることにしましょう。

Mojoの最新版は常に下記のサイトにあります。

手元にgitの環境がある方はgit cloneするのが楽ですが、⁠download]ボタンをクリックすると圧縮ファイルをダウンロードできますので、ない方はそちらを利用して適当なディレクトリに解凍しておいてください。安定版を使いたい方はgithubのかわりにsearch.cpan.orgから圧縮ファイルを落としてくるとよいでしょう。

Mojo本体のテスト

ダウンロード・解凍がすんだら、念のためMojo本体のテストを実行します。シェル(コマンドライン)からおなじみの呪文を入力してください(makeのコマンド名は環境によって異なります⁠⁠。

> perl Makefile.PL
> make test

テストに問題がなければアプリケーションの作成にかかりましょう。

ひな形を作成する

シェル(コマンドライン)から次のコマンドを実行します。

> perl script/mojo generate app HelloWorld

すると、このようなログとともにひな形アプリケーションが作成されます。

  [mkdir] /home/ishigaki/mojo/hello_world/script
  [write] /home/ishigaki/mojo/hello_world/script/hello_world
  [chmod] hello_world/script/hello_world 744
  [mkdir] /home/ishigaki/mojo/hello_world/lib
  [write] /home/ishigaki/mojo/hello_world/lib/HelloWorld.pm
  [mkdir] /home/ishigaki/mojo/hello_world/t
  [write] /home/ishigaki/mojo/hello_world/t/basic.t
  [mkdir] /home/ishigaki/mojo/hello_world/log

開発用サーバを立ち上げる

いま作成されたhello_worldディレクトリに移動して、サーバを起動してみましょう。

> cd hello_world
> perl script/hello_world daemon

すると「Server available at http://127.0.0.1:3000.」のような表示とともに、付属のスタンドアロンサーバが起動します。ブラウザでhttp://127.0.0.1:3000にアクセスしてみてください。⁠Hello Mojo!」という画面が出れば成功です。

HelloWorld.pmの中身を見てみよう

Ctrl+Cで一度サーバを落として、エディタで先ほど生成されたlib/HelloWorld.pmを見てみましょう。

package HelloWorld;

use strict;
use warnings;

use base 'Mojo';

sub handler {
    my ($self, $tx) = @_;

    # Hello world!
    $tx->res->headers->content_type('text/plain');
    $tx->res->body('Hello Mojo!');
}

1;

内容は、Catalystフレームワークを使ったことのある方ならおなじみのものでしょう。$txはMojoのトランザクションオブジェクト。Catalystのコンテキストに相当するものです。$tx->resにはレスポンスオブジェクトが格納されています。Mojoでは移植性を高めるため、アプリケーション内部から直接ヘッダやボディを出力することはしません。handlerの中では必要なものをレスポンスオブジェクトに格納するだけにして、最後にMojoが、そのレスポンスオブジェクトをもとに必要な処理を行うという流れになっています。

レスポンスオブジェクトの中身

このレスポンスオブジェクトの正体は、Mojo::Message::Responseのインスタンスです。ここにはさまざまなメソッド、オブジェクトが格納されていますが、ふだんよく使うのはこのくらいでしょうか。

$tx->res->code(ステータスコード)

レスポンスのステータスコードを設定します。

$tx->res->headers->content_length()

Content-Lengthヘッダの値を設定します。

$tx->res->headers->content_type()

Content-Typeヘッダの値を設定します。

$tx->res->headers->header(ヘッダ名, )

任意のヘッダの値を設定します。

$tx->res->body()

レスポンスのボディ(HTMLなど)を設定します。

$tx->res->cookies(クッキーの値)

クッキーを設定します。Set-Cookieヘッダに渡す文字列を入れることもできますが、通常はMojo::Cookie::Responseのオブジェクトを入れます。

そのほかのメソッドや、各メソッドの詳細については該当するクラスのPODやソースコードをご覧ください。

レスポンスオブジェクトの中身がわかったら、まずはcontent_typeやbodyの内容を差し替えて、お好みの画面を表示させてみましょう。お好みでYAMLやData::Dumpのようなモジュールを使って$txオブジェクトのダンプを表示してみたり、画像ファイルなどを表示してみるのもよいかもしれません。

連載第2回ではリクエストの取り扱いを追加していきます。お楽しみに。

おすすめ記事

記事・ニュース一覧