最近のミニブログ界ではJaikuがGoogleに買収されてからJaikuに人が入り始め、賑わってから少し経ちます。ミニブログで代表的なTwitterとJaikuは一見同じミニブログに見えて、APIとしては違うものを採用しています。
TwitterのAPIは基本的にRESTとBasic認証および出力フォーマット指定というAPIを採用しており、クライアントを作成する開発者はURLに対してGET/POST出来るライブラリと、XML/JSON/RSS/ATOMの中から自分の使いたいフォーマットを処理出来るライブラリを選ぶ事が出来ます。
またJaikuのAPIはBasic認証ではなくpersonal_keyと呼ばれるAPIKEYとユーザ名で認証します。取得系はTwitterとそれ程変わりませんが更新系は以前にも書いた通りJSONもしくはXMLRPCに限定されてしまっています。つまりJSONで更新したらJSONのレスポンスが、XMLPRCで更新したらXMLRPCのレスポンスが返されます。JSONが扱いにくい言語を使用する場合にはXMLRPCを強制されてしまう事になります。
さて今日はJaikuのAPIに限った話ではなく、Jaikuを使ってXMLRPCのクライアント実装と、XMLRPCサーバについての話をしたいと思います。
まず送受信されるデータについて。
XMLRPCは、決められたXML構成にメソッド名および構造化可能なパラメータをリクエストとして送信し、同じく構造化可能なレスポンスを受け取るXML送受信APIです。
リクエストフォーマットは以下の様な記述になります。
<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>メソッド名</methodName>
<params>
<param><value><string>パラメータ1</string></value></param>
<param><value><string>パラメータ2</string></value></param>
</params>
</methodCall>
またレスポンスフォーマットは以下の様になります。
<?xml version="1.0" encoding="utf-8"?>
<methodResponse>
<params>
<param>
<value>
<string>結果</string>
</value>
</param>
</params>
</methodResponse>
リクエストパラメータは「params」というノードを括られており、配列になっているのが分かるかと思います。また値が格納される「value」ノードには「<string>」や「<int>」といった、その値の型が定義されています。上で書いた通り、リクエストパラメータとレスポンスは構造化出来ますので、例えばレスポンスで構造体を表すならば
<?xml version="1.0" encoding="utf-8"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>メンバ1</name>
<value><int>157</int></value>
</member>
<member>
<name>メンバ2</name>
<value><string>Sample</string></value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>
と書く事が出来ます。詳しくはXMLRPCのオフィシャルサイトで確認出来ます。またオフィシャルサイトではXMLRPCを使った処理系毎の実装一覧やXMLRPCが使えるサービス一覧も確認出来ます。
ところで、Windows Live WriterやBlogWrite、ubicast Blogger等といったブログ投稿ツールはXMLRPCを使用してブログ記事を操作しています。それらAPIは以下の様に分類されています。
- Blogger API: Bloggerが提供してるAPI
- metaWeblog API: Blogger APIに足らない部分を補足する形で登場したAPI
- MovableType API: Movable Typeが提供してるAPI
- LiveJournal API: Bloggerが提供してる独自API
さてJaikuの場合、XMLRPCのインタフェースは一つしか公開されておらず(2007/11/01時点)、そのスペックは
presence.send({
user => 'your username as string',
personal_key => 'your personal key as string',
message => 'message as string',
optional icon => 'icon number as int',
optional location => 'location as string',
optional generated => 'generat flag as boolean'
})
こんなイメージとして表現出来ます。簡単な物をPerlで書くならば
jaiku.pl
#!/usr/bin/perl
use strict;
use Encode qw(from_to);
use XMLRPC::Lite;
use Data::Dumper;
my ($user,$personal_key,$message,$icon) = @ARGV;
from_to($message, "shiftjis", "utf8") if $^O eq "MSWin32";
print Dumper(XMLRPC::Lite
->proxy('http://api.jaiku.com/xmlrpc')
->call('presence.send', {
user => $user,
personal_key => $personal_key,
message => $message,
icon => ($icon || 300),
})->result);
と書く事が出来ますね。これをコマンドラインから
./jaiku.pl username xxxxxxx 本日は晴天なり
※「xxxxxxx」はpersonal_keyです。APIドキュメントの右下あたりに記述されています。と実行すればJaikuのステータスが更新されます。例では最終引数に省略可能なアイコン番号を付けていますので
./jaiku.pl username xxxxxxx 曇り 398
と実行すればといった感じにアイコンを付ける事が出来ます。
なお、Jaikuのアイコン番号に対する実際のアイコン対応表を作りました。
JavaScriptをOnにして頂いて、以下のリンクをクリックして下さい。
アイコンリストを表示さて話をXMLRPCに戻して、Perlでは「XMLRPC::Transport::HTTP」というXMLRPCを透過的にPerlのパッケージおよびサブルーチンとバインドしてくれるモジュールがあり、XMLRPCサーバを簡単に実装する事が出来ます。
例えば数値パラメータ2つ貰い足した結果を返すXMLRPCサーバならば以下の様に実装出来ます。
#!/usr/bin/perl
use strict;
use XMLRPC::Transport::HTTP;
package calc;
sub plus {
shift if UNIVERSAL::isa( $_[0] => __PACKAGE__ );
my $lhs = shift;
my $rhs = shift;
my $res = $lhs + $rhs;
return {result=>SOAP::Data->type('int' => $res)};
}
XMLRPC::Transport::HTTP::CGI
->dispatch_to('calc')->handle;
モジュール名がpackage「calc」に、メソッド名がサブルーチン「plus」にバインドされている事が分かるかと思います。これを実行するには
#!/usr/bin/perl
use strict;
use warnings;
use Encode qw(from_to);
use XMLRPC::Lite;
use Data::Dumper;
my $url = 'http://example.com/xmlrpc/calc.cgi';
warn Dumper(XMLRPC::Lite
->proxy($url)
->call('calc.plus', 1, 2)->result);
というクライアント側のコードで実行出来ます。勿論、XMLRPCを扱うならばクライアント/サーバはPerlでなくても良い訳です。pythonで実装するならば
from xmlrpclib import ServerProxy
proxy = ServerProxy("http://example.com/xmlrpc/calc.cgi")
print proxy.calc.plus(1, 2)
という実装になります。XMLRPCは既に色んな言語で実装されており、それぞれに使い方は異なりますが扱う仕様が決められている為に、移植に戸惑う事はそれ程ないかと思います。
※特にpythonに関してはメソッドバインディングされますので、かなり透過的に扱えます。
例を元にXMLRPCを説明して来ましたがどうでしたでしょうか?
色んな言語でJaikuクライアントを実装してみるのも面白いかもしれませんね。