タグ別アーカイブ: フレームワーク

Hokkaido.pm#7に参加してみた

 

Casualを含めて今回3度目の参加でした。今回はWEBアプリ再入門がテーマということで、WAF(ウェブアプリケーションフレームワーク)のお話が中心でした。WAFは選択肢豊富で迷いそうだけど、一方で、どれも大差ないようにも感じました。いずれにしても今、Perlが熱い。

Amon2(akiymさん)

高校生にあんな立派な発表されたら敵いません。KENT WEBの掲示板を移植していたのが面白かった。ああいうのをサクっと作れちゃうのは素晴らしい。スライドもう一度みたいなあ。あがってた

http://akiym.com/slides/20120512-hokkaidopm7-amon2/index.html

Dancer(aloelightさん)

Dancerは、ルーターに渡すコールバックでレスポンス用の文字列をreturnしていた点に、Mojoliciousとの設計の違いを感じました。あと、プラグイン数の比較がためになりました。

http://www.slideshare.net/aloelight/using-dancer

Mojolicious(jamadam)

MojoliciousでPHPライクなことをするお話をしました。

http://www.slideshare.net/jamadam/mojolicious-12907706

Ops Tools with Perl(riywoさん)

カバンがかっこよかったです。運用のお話は僕にはちょっと難しかったですが、cron blueprintのあたりは楽しげでした。あとDSLの作り方も興味深かった。

http://www.slideshare.net/riywo/ops-tools-with-perl-20120512-hokkaidopm

LTではお二方が音系のお話をされていたり、この日、一番の爆笑をとったapache依存のWAFのお話など、充実の内容でした。

懇親会では多くの方とお話しできて幸せでした。perlの次バージョンはuse strictがデフォになると初めて知りました。古くて危険なスクリプトがやっと淘汰されていくのかな。

昼につけ麺、夜にラーメンは反省点でした。腹壊しました。

Mojoliciousのバンドルファイルを整理するプラグイン

 

Mojoliciousのエラー画面で使われている画像やJSやCSS。リバースプロキシを拡張子などのホワイトリストで記述すると、これらのバンドルファイルがプロキシを通過せずに404エラーになってしまう。具体的にはこういうケース。

RewriteEngine on
RewriteRule ^(.*(.(html|htm|xml))|/)$ http://localhost:3000$1 [L,P,QSA]

バンドルファイルはなぜかpublic直下にちりばめられているため、記述しづらい。それにファイル名が衝突してることに気付かずハマりそう。そこで、バンドルファイルがあたかも単一ディレクトリにまとまってるかのように装うプラグインMojolicious-Plugin-UnmessifyBundleです。

sub startup {

    my $self = shift;

    # Mojolicious
    $self->plugin(unmessify_bundle => {prefix => 'mojolicious-bundle'});
}

# Mojolicious::Lite
plugin unmessify_bundle => {prefix => 'mojolicious-bundle'};

これを使うと例えばバンドルされたjqueryは/mojolicious-bundle/js/jquery.jsでアクセスできます。エラーページのHTMLソースも適当に書き換えられます。

すると、バンドルファイルをワンライナーでホワイトリスト入りさせることができるのです。

    RewriteEngine on
    RewriteRule ^(.*(.(html|htm|xml))|/)$ http://localhost:3000$1 [L,P,QSA]
    RewriteRule ^/mojolicious-bundle(/.+)$ http://localhost:3000$1 [L,P,QSA]

前回以上にニーズのなさそうなネタでした。

 

MojoliciousアプリにPlack::Middlewareをプラグインするプラグイン

レスポンスフィルター系のPlack::Middleware::*をMojoliciousのafter_dispachフックにねじ込むプラグインMojolicious-Plugin-PlackMiddlewareです。そんなニーズない?

MojoX::Tusuで古いウェブサイトを移植するとき、/mobile/なんてディレクトリがあったら、「Plack-Middleware-ForceCharset」で強制的にShift_JISで出力するとかしたい。現状でもソースでauto_detectするオプションがあるからいいんだけど、明示的にしたい。

enable_ifっぽい判定もできるようにしたので、きっとできると思う。

use MojoX::Util::ResponseFilter 'enable';

sub startup {

    my $self = shift;

    $self->plugin('plack_middleware', [
        'Plack::Middleware::Some1',
        'Plack::Middleware::Some2', {arg1 => 'some_vale'},
        'Plack::Middleware::ForceCharset', sub {
            my $c = shift;
            if (ルートが/mobile/だったら) {
                return 1;
            }
        }, {charset => 'Shift_JIS'},
    ]);
}

 

CSSでいじれるディレクトリツリーの生成スクリプト

ブログ記事にディレクトリーツリーを掲載しようと思ったんだけど、treeコマンドの出力は味気ないので、CSSでいじりやすくHTML出力できるperlスクリプトをチョー適当に作った。本来の仕事が進まない。

[2011.6.22]ソート追加

 

use strict;
use warnings;
use utf8;
use Getopt::Long;

    my %args = ('L' => 10);
    GetOptions(%args, 'L=s');
    my ($dir) = @ARGV;
    &loopDir($dir || '.', 0);
    exit;

    sub loopDir {
        my ($dir, $depth) = @_;
        chdir($dir) || die "Cannot chdir to $dir\n";
        opendir(my $dh, ".");
        my @entries = sort {$a cmp $b} grep {substr($_,0,1) ne '.'} readdir($dh);
        closedir($dh);
        if (scalar @entries) {
            print "<ul>\n";
            for my $f (@entries) {
                if (-d $f) {
                    print qq{<li class="dir">\n};
                    print qq{$f\n};
                    if ($depth < $args{L} - 1) {
                        loopDir($f, $depth + 1);
                    }
                    print qq{</li>n};
                } elsif (-f $f) {
                    print qq{<li class="file">$f</li>\n};
                }
            }
            print "</ul>\n";
        }
        chdir("..");
    }
  • crypt.pl
  • ddsn_get.sh
  • memo.txt
  • ffmpeg
    • 02.3gp
    • 02a.wav
    • 01a.3gp
    • 01a.wav
    • 02a.3gp
    • 2ch.mp3
    • test.3g2
    • brave
      • 01_2.avi.filepart
    • 01.3gp

 

CSSもかなりテキトー。

.directoryTree {
    padding:10px;
    border:1px solid #aaa;
    background-color:#fffbf0;
}
    .directoryTree ul ul {
        padding:0;
        margin-left:0;
        margin-bottom:0.5em;
        padding-bottom: 0 !important;
        border-left:3px solid #ddd;
    }
    .directoryTree li {
        margin-left:0 !important;
        padding-left:30px !important;
        vertical-align:bottom;
        background-repeat:no-repeat;
        background-position:10px 0;
        list-style:none;
    }
        .directoryTree li.dir {
            background-image:url(./images/xiao_icon/40.png);
            margin-bottom:0.5em;
        }
            .directoryTree li.dir > ul {
                margin-left:-1em;
            }
        .directoryTree li.file {
            background-image:url(./images/xiao_icon/21.png);
        }

Mojoliciousにウェブ制作をデプロイする

「ウェブアプリ開発」と「ウェブ制作」って別のジャンルなのかなあ。主に受託のコーポレートウェブ制作を生業にしていると流行りのウェブアプリケーションフレームワーク的なものにあまり馴染めない。まるで別世界の出来事のようだ。これって何となくURLディスパッチに対する発想の違いな気がしたので、Mojoliciousのディスパッチャを豪快に差し替えて、ウェブ制作を「デプロイ」できるようにした。apache風のディスパッチャをMojoliciousに登録する「MojoX::Tusu」。

  • リクエストパスはサーバーのディレクトリ階層を意味する。
  • テンプレートもstaticファイルもpublic_htmlに突っ込む。
  • server-parsedの対象は拡張子で決める。
  • apacheのDirectoryIndexに相当する機能。
  • apacheのErrorDocumentに相当する機能。
  • otherのread権限のないファイルへのアクセスは403エラー。
  • apacheを真似てディレクトリfooへのアクセスはfoo/にリダイレクトしてみた。

Mojoliciousルートにpublic_htmlを作り、手元にあったいくつかの静的サイトデータを突っ込んだところ、ビルトインサーバー, CGI, hypnotoad上で今までどおり動作しました。そして、PHPで言えば「AddType application/x-httpd-php .html」としたのと似た状態になり、htmlファイル内の好きなところに動的コンテンツを挿入できるという訳です。ただし、念のため先に書いておくと、Mojoliciousの標準のテンプレート命名規則(index.html.epとか)がMojoX::Tusuの差し替えたディスパッチャの方針と合致しないため、今のところepやeplは使えません。epRendererあたりをそっくり差し替えれば行けそうですが、とりあえず僕のお気に入りのテンプレートエンジン「Text::PSTemplate」でお楽しみください。

MojoX::Tusuを用いたMojoliciousアプリは下記のようになります。とりあえずrouteは必要ありません。

use MojoX::Tusu;
use strict;
use warnings;
use base 'Mojolicious';

sub startup {
    my $self = shift;
    my $tusu = MojoX::Tusu->new($self);
}

URLディスパッチに関しては内部的に下記のようなことをやってます。リクエストパスがテンプレートの在り処を意味するという訳です。ちなみにname('')としているのはテンプレート名が空(/へのアクセス)のとき、自動生成されたroute名がテンプレート名になってしまうからなのです。

$app->routes
    ->route('/:template', template => qr{.*})
    ->name('')
    ->to(cb => sub {$_[0]->render(handler => 'tusu')});

URLディスパッチルールが昔ながらのルールに乗っ取っているので、mojolicious rootが必要な場合意外はテンプレート内にurl_forと書く必要はありません。デザイナーさんが使うオーサリングソフトとの親和性も高いです。リンクパスの表記を巡っては、ここ1年くらいhtmlのbaseタグを活用して乗り切ってきたのですが、いろいろ面倒を抱え込むことにもなってやめたという経緯もあります。なお、このデフォルトのrouteは初回のon_processフックで登録してるので、startup内でルートが登録されればそちらが優先されます。

ドキュメントルート。内部的にはこうです。

$app->static->root('public_html');
$app->renderer->root('public_html');

Mojoliciousのデフォルトディスパッチャはstaticファイルを先に存在確認するようになってます。テンプレートとstaticを同じディレクトリに詰め込むと、全てstaticとして扱われてしまうので、フロントディスパッチャを組み直しています。デフォルトでは.htmlと.htmと.xmlだけテンプレートとして処理し、それ以外はstatic。ただし、DirectoryIndexの適用やパーミッションのチェックなどをして、エラーを返したりもします。なお、スクリプトファイルがあるとソースが見えちゃうので、リバースプロキシなりhtaccessなりで排除しないといけません。

お問い合わせフォームを作りたくなったら、もちろんrouteを追加することもできます。

sub startup {
    my $self = shift;
    my $tusu = MojoX::Tusu->new($self);
    my $r = $self->routes;
    $r->route('/inquiry/')->via('post')->to(cb => sub {
        ### メール送るとか
    })
}

ただし、MojoX::Tusu方式では、routeはあくまでディレクトリであって、inqueryコントローラーを意味しないってのは譲れないルールなのです。実際、/inquiry/へのアクセスの際には先ず/inquiry/index.htmlの存在確認がなされます。

 

public_html直下にindex.cgiを置いてCGIモードでも動かせます。その場合は

RewriteCond %{REQUEST_FILENAME} ((.(html|htm|xml))|/)$
RewriteRule ^(.*)$ index.cgi/$1 [QSA,L]

としておけば動くと思います。また、この場合、public_html内に既設のcgiやphpがあるとそのまま動くので、放っておきたい過去の遺物がある場合に便利です。

また、稼働中のサイトの一部のディレクトリにMojoX::Tusuを導入したい場合は、仮想的なドキュメントルートを作ってmojoliciousルートを跨ぎます。

RewriteEngine On
RewriteBase /path/to/root/
RewriteCond %{REQUEST_URI} ((.(html|htm|xml))|/)$
RewriteCond %{REQUEST_FILENAME} !index.cgi
RewriteRule ^(.*)$ public_html/index.cgi/$1 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !index.cgi
RewriteCond %{REQUEST_FILENAME} !public_html
RewriteRule ^(.*)$ public_html/$1 [QSA,L]

とすれば、外からは/path/to/root/a/b.htmlと見える物が/path/to/root/public_html/index.cgi/a/b.htmlを指すようになる、はず。mod_rewriteはちょっと自身なし。

 

MojoX::TusuはhtmlファイルをText::PSTemplateを使ってレンダリングするので、こんな感じでHTMLを拡張できます。

<html>
    <div>
        <% include('copyright.html') %>
    </div>

MojoX::Tusu(というかMojolicious)はテンプレートエラーをプリティに表示してくれるので、デザイナーさんでも作業しやすい。

 

 

 

 

あと、MojoX::Tusuは独自にプラグインとコンポーネントという仕組みも提供していて、いろいろ拡張できます。

つづく