perl



2011 12月12日

PerlでPayPalのExpressCheckoutを実装するのにBusiness::PayPal::APIを使っているのだけれど、日本語(2byte文字)がうまく送信できない。

UTF-8で送ろうが、フラグ付きにしようが、だ。

散々悩んだ挙句、原因はSOAP::Liteが勝手にbase64エンコードするからだと判明。

Business::PayPal::APIは内部でSOAP::Liteを使用していて、Asciiだとそのままなのだけれど、それ以外はbase64にエンコードする仕様の様子。

前々から、例えば、OrderDescription に日本語を使うと上手くいかないと思っていたのだけれど、、、。
仕方がないから Business::PayPal::API::ExpressCheckoutをカスタマイズする。

/usr/lib/perl5/site_perl/5.8.8/Business/PayPal/API/ExpressCheckout.pm

Selec All Code:
    ## add all the other fields
    for my $field ( keys %types ) {
	next unless defined $args{$field};
 
        if( $field eq 'MaxAmount' ) {
            push @secrd, SOAP::Data->name( $field => $args{$field} )->type( $types{$field} )
              ->attr( {currencyID => $currencyID, xmlns => $self->C_xmlns_ebay} );
        }
        ## 追記ココから
        elsif($field eq 'Address'){
            my @addr;
            my $hash = $args{$field};
            for my $f ( keys %$hash) {
               push @addr,  SOAP::Data->name( $f )->type(string => $args{$field}{$f} );
            }
            my $obj = SOAP::Data->name( $field => \SOAP::Data->value( @addr ));
            push @secrd,$obj;
        }
        ## 追記ココまで
        else {
            push @secrd, SOAP::Data->name( $field => $args{$field} )->type( $types{$field} );
        }
    }

SOAPなんて使ってたらダメだね…







2011 11月28日

MojoliciousアプリケーションをCGIで動かす時に、スタイルシートや外部JavaScriptファイル、画像など静的ファイルの扱いには注意が必要になる。

これはテンプレートでタグヘルパーを使った時、例えば

Selec All Code:
    <%= stylesheet '/css/style.css' %>

とスタイルシートを読み込んだつもりだけど、これはスタイルシートを読み込むCGIを実行するのと同じ(スタイルシートのURLにリダイレクト処理するCGIとして実行される)
静的ファイルを呼び出す回数分のCGIが実行されることになるので、パフォーマンスも悪くなることは当然ながら、データベースの接続処理をstartup内でしていたりすると実行回数分の接続を行う事となる。

以前speedyCGIとしてMojoliciousアプリケーションを動作させていた時に、MySQLの最大同時接続数が異常になってMySQLサーバがダウンした事もある。

MojoliciousでCSSなどの静的ファイルを利用する – サンプルコードによるPerl入門

 ローカル環境で試験をするときは、組み込みのWebサーバーがCSSなどの静的ファイルをディスパッチしてくれるので、パフォーマンスの問題は起こりません。一方さくらのレンタルサーバーではCGIというプロトコルを利用してWebアプリケーションを起動しています。CGIというプロトコルはひとつのアクセスに対してひとつのプロセスを立ち上げます。プロセスの起動という処理はとても時間がかかるので、静的ファイルをCGIでディスパッチするとパフォーマンスの劣化が顕著に見られることになります。

リンク先にあるように、組み込みのwebサーバやその他のプリフォークサーバ(starman等)ならば問題ないのかもしれない。まぁ、それ自体がwebサーバとして動作するものなので当然といえば当然か。

CGIとして動作させる場合の解決策としてmod_rewriteの利用が提唱されている。.httaccess(またはhttpd.conf)でApacheが静的ファイルは静的ファイルとして処理するようにmod_rewriteルールを設定する。

もう一つ解決する方法としては、タグヘルパーを使わずに

Selec All Code:
    <link href="/css/style.css" media="screen" rel="stylesheet" type="text/css" />

などと直接タグを書いてしまう方法。これはデプロイするときにディレクトリ構成が変わったりすると後々面倒(テンプレートをすべて修正する必要があるとか)なので、推奨される方法ではないのかもしれないけれど。

MojoliciousをCGI動作させていてパフォーマンスがイマイチだな・・・と思っているなら調べてみるといいかもしれない。

App.pmとかのstartup()内に

Selec All Code:
sub startup {
    warn 'warn CGI run.';
    ....
}

等としてアプルケーションを実行するとapacheのエラーログに記録されるので1度の実行で複数行のログが残っていたらその行数分アプリケーションが実行されていることになる。

Apacheでデプロイする様々な方法

Apache deployment – GitHub
Apache/CGI にmod_rewriteの設定が記述されている。その中の Pretty “Web 2.0″ URLs という項目は参考になる。







2011 10月15日

configファイルの読み込み

設定ファイルを読み込む / Mojoliciousリファレンス – サンプルコードによるPerl入門

 設定(コンフィグ)ファイルを読み込むにはMojolicious::Plugin::Configを利用します。

というように、Mojoliciousアプリで設定ファイルを使う事ができる。例えば etc/MyApp.conf を読み込むには以下のような感じ。 stash_keyはオプションで設定できる(デフォルトはconfig?)

etc/MyApp.conf

Selec All Code:
{
    # MyApp config
 
    # サービス名
    SARVICE_NAME => 'hogehoge',
 
    # 配列のリファレンス等
    CATEGORY => [0,1,2,3,4],
}

MyApp.pm

Selec All Code:
package MyApp;
 
sub startup {
    my $self = shift;
 
    # コンフィグファイル読み込み
    my $config = $self->plugin('config', { file => 'etc/MyApp.conf', stash_key => 'conf' });
    ....
}

読み込みはリンク先に詳しく書かれている。

configで設定された値を使う

コントローラーとかで使う

Selec All Code:
sub index {
    my $self = shift;
 
    #my $config = $self->stash('conf');
    my $config = $self->config;
    my $service_name = $config->{SARVICE_NAME};
    # or 
    my $service_name = $self->config('SARVICE_NAME');
    ....
}

テンプレートで使う

Selec All Code:
    <%= stash('conf')->{SARVICE_NAME} %>
    <%= config->{SARVICE_NAME} %>
    <%= config('SARVICE_NAME') %>

オブジェクト指向的には config()で取得したほうがいいのかな?

テンプレートで使うには

Selec All Code:
<%= config 'SARVICE_NAME' %>

がタイプが一番少ないようだ。







2011 10月14日

すぐ忘れるし、どこにあったか分からなくなるのでメモ。

Mojolicious – GitHubより引用

Selec All Code:
    package MyApp;
 
    use Mojo::Base 'Mojolicious';
 
    use DBIx::Custom;
 
    has dbi => sub {
        my $dbi = DBIx::Custom->connect(...);
        return $dbi;
    };
 
    sub startup {
        my $self = shift;
 
        ### YOU MUST NOT CALL dbi() method in starup().
    }

リンク先にはBad Exampleもあるので参考に。







2011 7月30日

DBIx::Custom – search.cpan.org
DBIx-Custom-0.1705

DBIx::Custom select メソッドの whereの項目を見ると様々な指定方法が出来ることが分かる。

注意する点はStringを渡す時。

Selec All Code:
where => "url = 'http://hoge.com/huga.cgi?key=value' ",

上のように条件に ? が含まれる場合、SQLの作成に失敗する。(DBIx::Custom::QueryBuilder::build_queryでかな?)

? がメタ文字として扱われるため?(\?とエスケープしてもダメ)

Hashリファレンスで渡すと大丈夫です。

Selec All Code:
where => {url => 'http://hoge.com/huga.cgi?key=value' },

これを踏まえてコードにすると、安全なのはこんな感じのコードになるのかな。

Selec All Code:
    my $id = 1;
    my $url = 'http://hoge.com/huga.cgi?key=value';
    $result = $dbi->select(
        table   =>  'table_name',
        column  => [qw/title content url/],
        where => [
                    ["and", "{= id}", "url = :url", "update_time > SUBDATE( NOW(), interval 7 day )"],
                    { id => $id, url => $url},
        ],
    );

※ {= id} は “id = :id” とも書ける(url = :urlも同様)。あえて両方含めてみた。

where にはDBIx::Custom::Whereオブジェクトも指定できますが、DBIx::Custom::Whereオブジェクトを生成する時にも同様で、? を含めた条件には注意が必要。

追記:タグ機能は廃止予定だそうです。
http://twitter.com/#!/perlcodesample/status/97162783644319744