Mojoを使ってみた

ちょろっと使ってみたのでレポートしてみる。

MojoというのはCatalystの原作者sriことSebastian Riedelが最近つくっている「ウェブアプリケーションフレームワークの土台をつくる」フレームワークのこと。本人いわく「rubyにおけるrack、pythonにおけるwsgiに相当するもの」だそうですが、その評価の是非はさておき、大きな特徴をいくつかあげると、

  • インストールはきわめて簡単
  • 「やってみたかったから」再発明
  • RFC大好き
  • コンテキスト持ち歩き系

というところでしょうか。国内では同じような趣旨のHTTP::Engineが開発されていますが、Mooseをバリバリ使っているHTTP::Engineに比べて、Mojoはアクセサからなにから、ほとんどのコードを自分で再実装しているので、インストールに困るような依存モジュールは(ほとんど)なし。ぶっちゃけ「さくらのレンタルサーバ」にまるっとFTPアップロードしてやればそのまま動きますし、Windows上でも(ふつうに使う分には)問題なく動作します。

また、私自身は試していませんが、MojoはHTTPの非常にマイナーな仕様まで実装してあることも売りのひとつ。実際、githubリポジトリのなかにはRFC2388、2616、2965、3986のテキストや、fastcgiの仕様書までコミットされているくらいですから、意気込みのほどは感じられるでしょう。

コード例はこれから載せていきますが、RequestやResponseを含むコンテキストを持ち歩くのはCatalystに似ています。HTTP::Engine界隈ではすでに否定されたやり方ですが、この辺は好みの問題ということで。
さて、本編。

現状の0.8シリーズで肝の部分はおよそ実装済みということになっているので、いつも通りにcpan Mojoしてもよいのですが、Mojoは適当なディレクトリにコピーするだけで十分使えるようになっているので、ここではgithubからtarballをダウンロード&解凍したディレクトリで作業していくことにします(もちろんできる人はふつうにgit cloneしてください)。

http://github.com/kraih/mojo/tree/master

解凍が済んだら、perl Makefile.PLを実行して依存モジュールを確認。万一欠けているものがあるようでしたらCPANから適当にインストールしましょう。make testして動作することを確認したら

perl bin/mojo generate app MyApp

としてアプリのひな形をつくります。my_appというディレクトリができますので、そちらに移動。今度は

perl bin/my_app daemon

を実行。例によってhttp://localhost:3000/にアクセスすると、シンプルな起動画面が表示されるという寸法。

ここで生成されているコードはこんな感じ。

package MyApp;

use strict;
use warnings;

use base 'Mojo';

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

    # $tx is a Mojo::Transaction instance
    $tx->res->code(200);
    $tx->res->headers->content_type('text/plain');
    $tx->res->body('Hello Mojo!');

    return $tx;
}

1;

この$txというのがCatalystの$cに相当するトランザクションオブジェクト。ここではディスパッチもなにもせず、ただHello Mojoを返していますが、もちろん実際のアプリではこのhandlerメソッドのなかにディスパッチャなりなんなりを入れて、$txを引き渡しながら必要な処理を行っていきます。

このまま付属のスタンドアロンサーバを使い続けてもよいのですが、レンタルサーバで使う場合、こういう自前のサーバを立てておくと怒られますから、ここではふつうのCGIとして実行することを考えます。Apacheなりなんなりの設定の仕方については触れないとして、index.cgiはこんなスクリプトになります。もちろん「/path/to/mojo」の部分は環境にあわせて変えてください。

#!/usr/bin/perl

use strict;
use warnings;
use lib "/path/to/mojo/lib";
use lib "/path/to/mojo/my_app/lib";

$ENV{MOJO_APP} = 'MyApp';

use Mojo::Server::CGI;
Mojo::Server::CGI->new->run;

で、MyApp本体のコードに戻りますが、毎回ディスパッチャを書くのは面倒という人のために、MojoにはMojoliciousという簡単なウェブアプリケーションフレームワークが同梱されています。

Mojoをインストールしたディレクトリに戻って、今度は

perl bin/mojolicious generate app MyApp

してみてください。古いMyAppを上書きする形で、Mojolicious風のひな形が用意されます。デーモンの起動法はさっきと同じ。CGIもそのまま動きます。リロードしてみればスタート画面が変わるのが確認できるはずです。

今度のMyApp.pmはこんな感じ。

package MyApp;

use strict;
use warnings;

use base 'Mojolicious';

# This method will run for each request
sub dispatch {
    my ($self, $c) = @_;

    # Try to find a static file
    $self->static->dispatch($c);

    # Use routes if we don't have a response code yet
    $self->routes->dispatch($c) unless $c->res->code;

    # Nothing found, serve static file "public/404.html"
    unless ($c->res->code) {
        $self->static->serve($c, '/404.html');
        $c->res->code(404);
    }
}

# This method will run once at server start
sub startup {
    my $self = shift;

    # Routes
    my $r = $self->routes;

    # Default route
    $r->route('/:controller/:action/:id')
      ->to(controller => 'example', action => 'welcome', id => 1);
}

1;

startupのマッピングルール以外は、自明でしょう。このルールについてはMojo::Manual::Mojoliciousに説明がありますので各自ご確認ください。

いわゆるコントローラの方はこうなります。

package MyApp::Example;

use strict;
use warnings;

use base 'Mojolicious::Controller';

# This action will render a template
sub welcome {
    my ($self, $c) = @_;

    # Render template "example/welcome.phtml"
    $c->render;
}

1;

テンプレートの中身はこう。

% my $c = shift;
<!doctype html>
    <head><title>Welcome to the Mojolicious Web Framework!</title></head>
    <body>
        <h2>Welcome to the Mojolicious Web Framework!</h2>
        This page was generated from the template
        "templates/example/welcome.phtml",
        <a href="<%= $c->url_for %>">
            click here
        </a> 
        to reload the page or
        <a href="/index.html">
            here
        </a>
        to move forward to a static page.
    </body>
</html>

ここではテンプレートに独自の(HTML::Masonチックな)記法を使っていますが、ディスパッチャともども、この辺はお好みで別のものに変更できます。

HTTP::Engineとのベンチやもっと細かな違いはそのうちどなたかが検証してくれると思いますが、軽く使ってみた限りではいい感じ。Mooseな人たちからは「(Mooseがあるのに)なんでいまさらアクセサ(やテンプレートエンジン)を再発明するんだ」と批判されていましたが、かならずしも恵まれた環境を使えるとは限らない受託メインの人にはこのくらい持ち歩きやすいものの方がありがたいでしょうし(これなら非プログラマな人でもメールひとつでインストールしてもらえそうですし、アプリを書籍などに添付するのも簡単になりそう)、Mojoliciousのオフィシャルサイトにもあるように、CGI.pmを置き換えるものとしては十分なんじゃないかと思います。

もともと最初のリリース時にはMojo、Curse、Nevermore、Voodooという四つのネームスペースを使っていたくらいで、内容的にちょっとごちゃごちゃしている感は否めませんが、つまらないコメントを除けばコードも読みやすいので、Mooseはちょっと、と尻込みしていた方はぜひお試しあれ。