Flex⇔Perl連携 その1

気付いたら1ヶ月更新してなかった…ひと夏ってあっという間ですね。
1ヶ月も経つと赤子も成長しまくり。寝返りを覚えた!!


仕事でレポート画面作ることになりそうなので
Flexでちょちょいと作ってみよーと思い調査してました。
もう何か、HTML書くの面倒。

Perlが無い

で、バックエンドどうしようと。
以前にS2Flex2の紹介しましたが、やっぱいろいろ面倒かなーと*1
Scaffoldは魅力的なんですけどね。


調べてみると、PHPとかRubyとかPythonとかで出来そうな感じ…


あれ。Perlは?w


PerlFlexは流行ってないんですかね。
てかAMF3の実装が無いから?*2

半分意地

もう何か一時期「PHPでやったらいいじゃん」っていう雰囲気になりましたが、やっぱりPerlでもやりたい…
だって… Perlが好きなんです!


まあ普通にXMLでやっても問題ないだろうし、
AMF0の実装はすでにあるし、なんとかなるべー。
いろいろな形式でやりとりしてみて、データ表示出来ればOKとしよう。


HelloWorld FlexPerl

http://www.adobe.com/jp/devnet/flex/articles/flex_plus_ll.html
まずは、こちらにあるHelloWorldプロジェクトにPerl実装をしてみましょう。

クライアント

上記サンプルソースの、HelloWorld.mxmlのsayHelloメソッドを
以下のように直します。

HelloWorld.mxml

private function sayHello():void
{
    var client:IServiceClient;

    switch (lang.selectedValue)
    {
        case RUBY:
            client = new RubyClient(this);
            break;
        case PHP:
            client = new PHPClient(this);
            break;
        case PYTHON:
            client = new PythonClient(this);
            break;
        case PERL:
            client = new PerlClient(this);
            break;
        default:
            throw new Error("Invalid selection.");
    }

    if (client != null)
    {
        const useAMF0:Boolean = lang.selectedValue == PERL;
        client.callRemote(useAMF0);
    }
}

そして、PerlClient.asを同じ階層に配置します。(ソースは以下参照)
http://github.com/toritori0318/Flex_Perl/blob/ede99dbb67122a975a65e032b312b24c37e0462e/HelloWorldPerl/client/src/PerlClient.as
他の言語とほとんど同じことをしているだけです。

サーバ

PerlでのAMFパースですが、typesterさんのData::AMFが良さげなので、こちらを使ってみます。*3
サーバスクリプトのサンプルがあったのでこれをそのまま使おうとしたのですが…
http://cpansearch.perl.org/src/TYPESTER/Data-AMF-0.02004/examples/
HTTP::Engineのバージョン違いで動かなかったので、ちょっと直してみました。

simple_server_mod.pl

#!/usr/bin/perl
 
use strict;
use warnings;
use FindBin::libs;
use Data::AMF::Packet;
use List::Util ();
use Path::Class;
use Data::Dumper;
 
use HTTP::Engine;
 
&main;
exit;
 
sub main {
    my $engine = HTTP::Engine->new(
        interface => {
            module => 'ServerSimple',
            args => {
                host => 'localhost',
                port => '3000',
            },
            request_handler => \&handler,
        },
    );
    $engine->run;
}
 
sub handler {
    my $req = shift;
    if ( $req->uri->path eq '/gateway' ) {
        my $fh = $req->body;
        my $body = do { local $/; <$fh> };
 
        my $request = Data::AMF::Packet->deserialize($body);
 
        my @result;
        for my $message ( @{ $request->messages } ) {
            my $method = __PACKAGE__->can( $message->target_uri );
 
            if ($method) {
                my $result = $method->( $message->value );
 
                push @result, $message->result($result);
            }
        }
 
        my $response = Data::AMF::Packet->new(
            version => $request->version,
            headers => [],
            messages => \@result,
        );
 
        return res( 'application/x-amf', $response->serialize );
    }
    else {
        return res( 'application/x-shockwave-flash',
            scalar file('./examples/simple_flash_remoting.swf')->slurp );
    }
}
 
sub res {
    my ( $content, $body ) = @_;
    HTTP::Engine::Response->new(
        content_type => $content,
        body => $body
    );
}
 
sub echo {
    return $_[0];
}
 
sub sum {
    return List::Util::sum( @{ $_[0] } );
}
 
sub dump {
    use YAML;
    warn Dump $_[0];
}
 
1;

動かす

まず、サーバ側でsimple_server_mod.plを実行します。

[toritori0318@localhost script]$ perl simple_server_mod.pl
HTTP::Engine::Interface::ServerSimple : You can connect to your server at http://localhost:3000/

あとは、先程のFlexプロジェクトから文字列を送信してみましょう!


おk。


今回使用したスクリプトgithubに置いてありますのでなんなりと。
http://github.com/toritori0318/Flex_Perl/tree/master


それでは次回、いろいろなフォーマットでサーバと連携する実装を開発してみたいと思います。

*1:というか未だにJava苦手

*2:後述しますが、cpanにいくつかモジュールはあります

*3:現在、AMF0にしか対応していないようです