はじめに
「Mojolicious XML-RPC Pluginの開発」のその2です。
本内容では、前回の内容を踏まえ、XML-RPC実装を、Mojoliciousのプラグイン機能を使用して実装しようと思います。
説明は以下の順序で行います。
- Mojolicious XML-RPC Plugin(以下 「FrontierXMLRPC」)とは
- 「FrontierXMLRPC」作成方法
- 「FrontierXMLRPC」使用方法
- 「FrontierXMLRPC」テスト手順
1. Mojolicious XML-RPC Pluginとは
(その1)で行ったXML-RPCの実装を、以下の順序で再実装しようという試みです。
- (1) 「FrontierXMLRPC」を作成する。
- (2) 「FrontierXMLRPC」上でXML-RPC関数を実装する。
「FrontierXMLRPC」プラグインは以下を目標に作成しました。
- 単純にMojoliciousのプラグイン作成お勉強
XML-RPCプラグインなんてどこかにはあると思いますが
 軽く調べたところ、目標に合致したものは公開されてないっぽい。
- 簡単設定で関数をexportできる。
- XML入出力を記録できる。記録する処理をコールバックできる。
1.1 「FrontierXMLRPC」概要図
以下に「FrontierXMLRPC」の概念を示します。
XML-RPCクライアント(python)
 -> Mojolicious雛形
  -> 「FrontierXMLRPC」読み込み
   -> 「FrontierXMLRPC」register関数
    -> コールバッククラス
「「FrontierXMLRPC」読み込み」については、「3.「FrontierXMLRPC」使用方法」 にて説明します。
その他は、「2.「FrontierXMLRPC」作成方法」にて説明します。
1.2 本文書でのサンプルについて
サンプルの実装は、[mojoxmlrpcplugin]に置いてあります。
サンプルには以下の内容が入っています。
- 「FrontierXMLRPC」Mojolicious Plugin ソース (以下: FrontierXMLRPC)
- 「FrontierXMLRPC」結合テスト用アプリケーション (FrontierXMLRPC/t/combined/)
2. 「FrontierXMLRPC」作成方法
「FrontierXMLRPC」は以下のように作成しました。
- Mojolicious Plugin 雛形作成
- 「FrontierXMLRPC」register関数作成
- コールバッククラス作成
以下に、個々の作成内容について説明します。
2.1 「FrontierXMLRPC」作成手順詳細
(1) Mojolicious Plugin 雛形作成
最初に、以下のコマンドで、Mojolicious Pluginの雛形を作成します。
$ mojo generate plugin FrontierXMLRPC
Mojolicious Pluginの名前を、「FrontierXMLRPC」としています。
コマンドを起動すると、以下のようなファイルが生成されます。
    Mojolicious-Plugin-FrontierXMLRPC/
      Makefile.PL
      lib/
        Mojolicious/
          Plugin/
            FrontierXMLRPC.pm
      t/
        basic.t
主に修正/追加するファイルは、以下の通りです。
- lib/Mojolicious/Plugin/FrontierXMLRPC.pm
- lib/Mojolicious/Plugin/FrontierXMLRPC/RPC2.pm(追加)
- テストコード t/01_load.t,02_xml.t
その他はサンプルに格納されているので、詳細はサンプルを確認してください。
(2)「FrontierXMLRPC」register関数 修正(FrontierXMLRPC.pm)
Mojolicious Pluginの中心は「register」という関数です。雛形のFrontierXMLRPC.pm内、resister関数を以下のように変更します。
package Mojolicious::Plugin::FrontierXMLRPC;
use Mojo::Base 'Mojolicious::Plugin';
our $VERSION = '0.01';
use Frontier::RPC2;
my $log = Mojo::Log->new;
sub register {
   my ($self, $app, $conf) = @_;
   #$log->info("FrontierXMLRPC\n");
   # XMLRPC
   my $server = Frontier::RPC2->new( 'encoding' => 'UTF-8' );
   if ( !defined $server ) {
       return ;
   }
   # parameter settings
   $self->{'method'} = $conf->{methods};
   $self->{'cb'} = $conf->{cb};
   $self->{'rpc2'} = $server;
   my $r = $app->routes;
   # prepare "/RPC2"
   $r->post("/RPC2")->to(namespace => 'Mojolicious::Plugin::FrontierXMLRPC::Rpc2'
       , action=>'proxy_xmlrpc',
       frontier_xmlrpc_plugin => $self,
   );
   return ;
}
1;
__END__
上記で重要なところは、以下の二つです。
- 「FrontierXMLRPC」register関数呼び出し時の情報をstash->frontier_xmlrpc_plugin(後述)経由でコンテキスト($self)に設定する
- コントローラクラスの追加(“/RPC2″時)
「FrontierXMLRPC」Mojolicious Pluginがコントローラクラスに値を渡す方法として
 stash->frontier_xmlrpc_pluginを使用しています。
以下で、register関数から情報を受け渡す対象の、「FrontierXMLRPC」コントローラクラスについて、説明します。
(3)「FrontierXMLRPC」コントローラクラス(RPC2.pm)追加
「FrontierXMLRPC」コントローラクラスは、(その1)で追加した、コントローラクラス(Method.pm)と、基本は一緒です。
- (1) XML-RPCリクエスト受信
- (2) Frontier::RPCライブラリに入力
- (3) Frontier::RPCライブラリから返却された、XML-RPCレスポンスを、まるごとWebクライアントに返却
「XML-RPCサーバ」のコントロールクラスと「FrontierXMLRPC」のコントローラクラスとの違いは以下の通りです。
- 起動時のregister関数から情報受信
stash->{frontier_xmlrpc_plugin}取得
- コールバック実装追加
「stash」とは、Mojolicious上のアプリケーションで、現在のリクエストが使用する値を、保存するための領域です。
本プラグインでは、「FrontierXMLRPC」register関数(プラグイン開始時)で作成した情報を、アプリケーション経由でコントローラへ受け渡すための領域として使用しています。
frontier_xmlrpc_plugin としたのは、本プラグインで名づけたものです。(もっといい方法があるのかもしれません)
コールバックは、HTTPリクエスト/レスポンスの記録用コールバックのために追加しています。
具体的な実装は以下の通りです。
XMLRPC controller
package Mojolicious::Plugin::FrontierXMLRPC::Rpc2;
use Mojo::Base 'Mojolicious::Controller';
use Frontier::RPC2;
use Data::Dumper;
sub proxy_xmlrpc {
   my $self = shift;
   my $plugin = $self->stash->{frontier_xmlrpc_plugin};
   if ( ! defined $plugin ) {
       return;
   }
   my $methods = $plugin->{'method'};
   my $server  = $plugin->{'rpc2'};
   my $cb = $plugin->{'cb'};
   if ( ! defined $server or ! defined $methods ) {
       return;
   }
   my $body = $self->req->body;
   #translate from request(XML) to response
   my  $response = $server->serve($body, $methods);
   #modify HTTP response
   $self->render(text=>$response, format=>"xml");
   # callback
   if ( defined $cb ) {
       &$cb($body, $response);
   }
}
1;
3.「FrontierXMLRPC」使用手順
「FrontierXMLRPC」をアプリケーションで使用する方法を示します。
3.1 インストール方法
以下の手順でインストールします。
$ cd Mojolicious-Plugin-FrontierXMLRPC $ perl Makefile.PL $ make $ make install
3.2 「FrontierXMLRPC」使用方法
「FrontierXMLRPC」は以下のように使用します。
(1)「FrontierXMLRPC」読み込み
「FrontierXMLRPC」を使用するには、アプリケーションのstartupにプラグインと、XML-RPC関数を登録します。
(2) XML-RPC関数登録
XML-RPC関数登録の方法は以下の通りです。
- XML-RPC関数の実装
- methodsの記述
methodsの記述方法は、[Frontier-RPC2]を参考にしてください。
(1)(2)を設定すると以下になります。
#XMLRPC コールバック
sub callback {
    (my $req,my $res)=@_;
}
# This method will run once at server start
sub startup {
  my $self = shift;
  #外部メソッド名と内部関数の紐付け設定
  my $methods = { 'xml.rpctestplus' => \&xmlrpcplus
            , 'xml.rpctestminus' => \&xmlrpcminus
            , 'xml.rpctestmixed' => \&xmlrpcmixed
    };
  #プラグインへのパラメータ
  my $xconf = {
    methods=>$methods,
    callback=>\&callback,
  };
  $self->plugin('Mojolicious::Plugin::FrontierXMLRPC',$xconf);
}
#API
sub xmlrpcplus {
   (my $a , my $b) = @_;
}
sub xmlrpcminus {
    (my $a , my $b) = @_;
}
sub xmlrpcmixed {
    (my $a , my $b) = @_;
}
4. 「FrontierXMLRPC」のテスト方法
単体テストと、結合テストの手順を示します。
4.1 単体テスト
Mojoliciousには(フレームワークなので)単体テスト方法があります。
perlの通常の単体テスト方法とほぼ変わりません。
単体テストは以下のように行います。
$ perl t/01_load.t $ perl t/02_xml.t
01_load.tは、プラグイン実装が読み出せるかどうか、02_xml.tは実際にプラグインへ
XML-RPC関数を登録し、関数が呼び出せたかどうか確認しています。
実行すると以下のようになります。
$ perl t/01_load.t ok 1 - use Mojolicious::Plugin::FrontierXMLRPC; 1..1 $ perl t/02_xml.t This is callback $VAR1 = '<?xml version=\'1.0\'?> <methodCall> <methodName>xml.rpctestplus</methodName> <params> <param> <value><int>1</int></value> </param> <param> <value><int>2</int></value> </param> </params> </methodCall>'; $VAR1 = '<?xml version="1.0" encoding="UTF-8"?> <methodResponse> <params> <param><value><i4>6</i4></value></param> </params> </methodResponse> '; ok 1 - POST /RPC2 ok 2 - 200 OK ok 3 - content is similar 1..3
単体テスト全体を一度に行うなら、以下のようにします。
$ prove t/01_load.t .. ok t/02_xml.t ... ok All tests successful. Files=2, Tests=4, 2 wallclock secs ( 0.08 usr 0.05 sys + 1.61 cusr 0.27 csy s 2.01 CPU) Result: PASS
4.2 結合テスト
結合テストは、以下の手順で行いました。
- 「FrontierXMLRPC」をインストール
- テスト用アプリケーションにて、「XML-RPCサーバ」と同様の関数を定義
- テスト用アプリケーションを起動した後、XML-RPCクライアントを起動する。
サンプルにある、テスト用アプリケーションを起動した結果が以下の通りです。
$ cd t/combined/fxmlrpc_test/ $ script/fxmlrpc_test daemon --listen http://0.0.0.0:50030
xmlrpc_client.pyのURLを変更してアクセスした結果が以下です。
1 + 2 : 3
>xmlrpc_client.py
3 - 2 : 1
{'a': 'b', 'c': [1, 3, 2], 'b': 1500000000}
5. 終わりに
perlのお勉強として、Mojoliciousを題材にしました。
意外と手軽に扱えるので、いいのではないかと思います。
 
											