諸事情によりレガシーなXMLRPC::LiteベースのプログラムをPlack上にポートすることになったので色々悪戦苦闘してみた。とりあえず普通に動かすのは辛い、ということはなんとなくわかったので色々やった結果、こんな感じのコードを書けばとりあえずディスパッチは動くようになった。もしベターな方法があったら教えて下さい(XMLRPC::Lite以外のベターなライブラリでもOK!)
(追記:指摘を受けたのでRPC::XMLで書き直してみた)
use strict; use Plack::Builder; use CGI::Emulate::PSGI; use IO::String; use XMLRPC::Transport::HTTP; my $xmlrpc = XMLRPC::Transport::HTTP::CGI->dispatch_to( "MyApp" ); builder { my $code = CGI::Emulate::PSGI->handler(sub { $xmlrpc->handle; }); sub { my $env = shift; my $io = $env->{'psgi.input'}; my $content = do { local $/; <$io> }; $env->{'psgi.input'} = IO::String->new($content); delete $env->{'psgix.io'}; local %ENV; $code->($env); }; };
psgi.inputに関してはPOSTデータを読み込むのにSOAP::Lite側で Plack::TempBufferをsysreadしようとしていて、そうすると必ず 0 を返すのですな。open()で作れる疑似ファイルハンドルやなんかでお茶を濁そうとがんばって見たのだけど、結局IO::Stringのようにtieしないと動かないという結論に
なんで local %ENVしてるのかは忘れちゃった。
というわけでこうして動くサーバーは作れたのだけど、なんか他に良い方法あるのかなー