uzutaka's notes

web系ソフトウェア開発,プログラミングなどについてまとめます.

PerlのWAF,Amon2の使い方とサンプルアプリケーション

同期との勉強会で発表した,Amon2の導入についての資料をまとめました.

  • Amon2を初めて利用する人向け
  • 単純なWebアプリを動かすところまでを説明します

Amon2とは

Amon2とはPSGI/PlackベースのWeb Application Frameworkで,非常に薄く軽量でありながら高い拡張性を持ち,Web系企業の大規模なシステムでの使用実績があります.
公式サイトはこちら Amon2 - Web application framework for Rapid web development

Amon2のインストール

以下,Amon2のバージョンは5.16です.執筆時最新版の6.00でも正常に動作することを確認しています.

$ cpanm Amon2 Carton
()

$ amon2-setup.pl AmonSample
-- Running flavor: Basic --
... (中略) ...
Setup script was done! You are ready to run the skelton.

You need to install the dependencies by:

    > carton install

And then, run your application server:

    > carton exec perl -Ilib script/amonsample-server

起動

carton installはしばらく時間がかかります.

$ cd AmonSample
$ carton install
Installing modules using /Users/takanori/AmonSample/cpanfile
Successfully installed Test-Harness-3.29
.. (中略) ...
Complete! Modules were installed into /Users/takanori/AmonSample/local

$ carton exec perl -Ilib script/amonsample-server
AmonSample: http://127.0.0.1:5000/

ブラウザで確認

localhost:5000へアクセス

f:id:uzutaka:20131127015642p:plain

ディレクトリ構成

builder      (Module::Build用設定)
config       データベースなどの設定ファイル
db           sqliteなどのデータベースファイル(mysqlなら使わない)
lib          perlファイル 主にこの中身をいじる 
local        (Cartonがインストールした依存モジュール)
script       起動スクリプト
sql          sqlファイル
static       js, css, image などの静的ファイル
t            テストファイル
tmpl         Xslateテンプレート
xt           (モジュールの作者専用テスト)

Router

# lib/AmonSample/Web/Dispatcher.pm
package AmonSample::Web::Dispatcher;
use strict;
use warnings;
use utf8;
use Amon2::Web::Dispatcher::RouterBoom;

any '/' => sub {
    my ($c) = @_;
    return $c->render('index.tx');
};

post '/account/logout' => sub { 
    my ($c) = @_;
    $c->session->expire();
    return $c->redirect('/');
};

1;

Template

<!-- tmpl/index.tx -->
: cascade "include/layout.tx"

: override content -> {

<h1>Hello, Amon2 world!</h1>

: }
<!-- tmpl/include/layout.tx -->
<!doctype html>
<html>
<head>...(中略)...</head>
<body>
    <div class="container">
        <div id="main">
            <: block content -> { } :>
        </div>
    </div>
</body>
</html>

Webアプリを作ってみる

  • 機能
    • テキストを挿入できる
    • 最新の1件を閲覧できる
  • 構成

変更する点を順番に見ていきましょう.

db設定

# config/development.pl
+{
    'DBI' => [
        'dbi:mysql:amonsample', 'YourUserName', 'YourPassword',
        +{ mysql_enable_utf8 => 1 },
    ],
};
-- sql/mysql.sql
CREATE TABLE IF NOT EXISTS memos (
    id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
    text TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# lib/AmonSample/DB/Schema.pm
table {
    name 'memos';
    pk 'id';
    columns qw(id text);
};
# root以外のユーザの場合,適切な権限が必要
$ mysqladmin -uYourUserName create amonsample -p
$ mysql -uYourUserName amonsample < sql/mysql.sql -p  

Model設定

# lib/AmonSample/DB.pm
...(略)...
sub latest_text {
    my ($self) = @_;
    my ($row) = $self->search(
        'memos',
        {},
        { order_by => {'id' => 'DESC'}, limit => 1 }
    );
    return $row->get_column('text') if ($row);
}

sub insert_memo {
    my ( $self, $text ) = @_;
    $self->insert( 'memos', { text => $text } );
}

1;

Router設定

# lib/AmonSample/Web/Dispatcher.pm
...(略)...
get '/memo' => sub {
    my ($c) = @_;
    my $latest_text = $c->db->latest_text;
    $latest_text //= "No comment";
    return $c->render( 'memo.tx', { latest_text => $latest_text } );
};

post '/memo/insert' => sub {
    my ($c) = @_;
    my $text = $c->req->param('text');
    $c->db->insert_memo($text);
    return $c->redirect('/memo');
};

1;

Template設定

<!-- tmpl/memo.tx -->
: cascade "include/layout.tx"

: override content -> {

<h2><: $latest_text :></h2>

<form method="post" action="<: uri_for('memo/insert') :>">
  <textarea name="text" rows="3"></textarea>
  <input type="submit" value="Submit">
</form>

: }

動作確認

localhost:5000/memo へアクセス

f:id:uzutaka:20131127021343p:plainf:id:uzutaka:20131127021352p:plain


Amon2のごく基本的な使い方を紹介しました.とても使いやすいフレームワークですので,ぜひ一度試してみてください.