スクリプトのお勉強 技術

Mojolicious XML-RPC Pluginの開発(2)

投稿日:

はじめに

「Mojolicious XML-RPC Pluginの開発」のその2です。

本内容では、前回の内容を踏まえ、XML-RPC実装を、Mojoliciousのプラグイン機能を使用して実装しようと思います。

説明は以下の順序で行います。

  1. Mojolicious XML-RPC Plugin(以下 「FrontierXMLRPC」)とは
  2. 「FrontierXMLRPC」作成方法
  3. 「FrontierXMLRPC」使用方法
  4. 「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関数登録の方法は以下の通りです。

  1. XML-RPC関数の実装
  2. 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を題材にしました。

意外と手軽に扱えるので、いいのではないかと思います。

-スクリプトのお勉強, 技術

執筆者:

関連記事

神奈川県横浜市神奈川区のワクチン接種地図作った

作ってみた。東白楽駅を真ん中にしてみました。なんとなく真ん中な感じなので。 データ元 以下のテキストデータからゴニョゴニョしてます。 https://www.city.yokohama.lg.jp/k …

VMware player(workstation) から WSL2に乗り換える

いままで、VMware player(今のVMWare Workstation Player)上で、作って確認していたけど、いちいち起動するのがだるいです。 ついでにやたらとリソースを使用するので、こ …

Markdown to HTML(grip)

1.はじめに 最近の文書はほとんどMarkdownで書くのですが、それをHTMLに変換する方法を調べました。 ただし、私がMarkdownと思っている文法は「github-flavored-markd …

seaborn + Pandas + Python によるグラフ描画(その1: 準備編)

グラフ描画してみよう 今現在の仕事で、グラフ描画する可能性があるので、少し練習してみようと思います。 題材について 突然ですが、私は確定拠出型年金に加入しています。証券会社はSBI証券 にしています。 …

vscodeのRemote Developmentで「権限がない」と怒られた時

小ネタです。 vscodeのRemote Developmentにてパスワードなしログイン vscodeは時々使うのですが、リモート開発するのにRemote Developmentが便利なので使ってま …