XML_RPC サーバを作る(PHPで)

XML-RPC Specification
http://www.futomi.com/lecture/japanese/xml_rpc.html

*概要
XML-RPC は、インターネット上で動作する Remote Procedure Calling プロトコルです。
XML-RPC メッセージは、HTTP-POST リクエストです。リクエストのボディーは XML です。プロシージャーはサーバー上で実行され、それが返す値もまた XML で整形されています。

ふむ。
XML_RPCもトラックバックPingもそうだけど、
所定の規格のリクエストがHTTP-POSTされるから、何とかしろと。

↓こんなのが飛んでくるから、XML-RPCサーバさんは何とかすること と。

POST /RPC2 HTTP/1.0
User-Agent: Frontier/5.1.2 (WinNT)
Host: betty.userland.com
Content-Type: text/xml
Content-length: 181
<?xml version=”1.0″?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>

んで、こんなイメージで。

関数名(引数1, 引数2, 引数3)
↓ ↑
<methodCall>
<methodName>関数名</methodName>
<params>
<param>
<value><i4>引数</i4></value>
</param>
<param>
<value><string>引数</string></value>
</param>
<param>
<value><boolean>引数</boolean></value>
</param>
</params>
</methodCall>

そう。
関数名と引数にあたるところが取得できれば、こっちのもの。
リクエストにたいして、内部では適切な処理を行って、レスポンスを返せばよい。
何も難しくない。

ここまでわかっていれば、あとはゴリゴリ自力でプログラムを書いたってよいのだけど、それはいわゆる、車輪の再発明というやつで、勉強にはなるけど、無駄なことこの上ない。
XML-RPCの仕様がいくらシンプルだといっても、きちんと書けば1000行2000行のプログラムになる。

というわけで、下記のような、すでに作成されている実装を利用する。

実装 特徴
Usefulinc
XML-RPC CLASS
XML-RPC for PHP Homepage
もともと、UsefulincのEdd Dumbillが開発したもので、市販本の中には、この実装クラスを利用した例を多く見かける。便利なクラス群のおかげで、クライアント、サーバの記述が簡単に行える。
PEAR
XML-RPC Package
http://pear.php.net/package-info.php?pacid=17
上記の、Usefulinc XML-RPC CLASSを、Stig BakkenがPHP PEARへ移植を行ったもの。完成度が高く、広く利用されている。
PHP付随の
拡張パッケージ
http://xmlrpc-epi.sourceforge.net/
PHP本体バージョン 4.1.0 以降に、XML-RPC 拡張モジュールとして付随しているもの。現在のところ(バージョン 4.3.2)まだ実験段階であり、デフォルトでは有効となっていない。実装部分がC言語で記述されているので速度面で有利。

ほか、各種CMS、各種phpのフレームワークが実装していて、ソースをいただくと使えてしまう。
Drupal のなかとか、CodeIgniter のなかとか…
(”xmlrpc.php”なんてファイル名を検索してみると、たくさんひっかかる)

どれにしようかなというところだけど、PEARのは探せば結構みんな使ってる。

で、あまり利用例がない、phpの拡張 XML-RPC関数を使ってみる。
ソースコードやファイルがやたらと増えないのが、個人的に好き。

________

■まず、たぶんこう使うように作ったんだろうな という方法

<?php
function sample_func($method_name,$params,$conf){
return array(‘tm’=>time());
}
$request=$HTTP_RAW_POST_DATA;
$xmlrpc=xmlrpc_server_create();
$conf=array();
xmlrpc_server_register_method($xmlrpc,”sample.echo”,”sample_func”);
$response=xmlrpc_server_call_method($xmlrpc,$request,$conf,array(
“output_type”=>”xml”,
“escaping”=>array(“markup”),
“version”=>”xmlrpc”,
“encoding”=>”UTF-8”));
header(“Content-type: text/xml;charset=UTF-8”);
echo $response;
xmlrpc_server_destroy($xmlrpc);
?>

1. POST されてくる HTTP リクエストの body 部分の XML を受け取る。
2. XMLRPC サーバを作成する。この時点では何も扱うことのできないサーバ。
3. XMLRPC サーバに関数を登録する。
4. POST されてきた内容を XMLRPC サーバ関数に渡して、XMLRPC の処理を行い、返り値を得る。
5. XMLRPC サーバ関数の返り値は XMLRPC のレスポンスとして送信するべき XML になっているので、それをクライアントに返す。
6. XMLRPC サーバを終了する。
________

XMLRPCサーバに登録できるのは関数名だけみたい。
上のサンプル程度の使い方ならよいとして、何かしらのフレームワークに組み込むとかしたいとき、使いにくそうではある。

でも、下のような使い方もできるので、何とでもなりそう。

■xmlrpc_server_create() しない式

//リクエストのXMLがPOSTで送られてくる
$r = file_get_contents(“php://input”);

//リクエスト解析
$a = xmlrpc_decode_request($r, $m);

//処理をする
//method は $m, 引数は $a。後は何とかする。

//返事する(response)
$xml= xmlrpc_encode(1);
header(‘Connection: close’);
header(‘Content-Length: ‘. strlen($xml));
header(‘Content-Type: text/xml’);
header(‘Date: ‘.date(‘r’));
echo $xml;

たとえば、ブログの更新Ping送信先にこれを書いたphpを指定して、何か新規記事を書いてみれば、

var_dump($r, $m, $a, $xml);

string(327) “<?xml version=”1.0″?>
<methodCall>
<methodName>weblogUpdates.extendedPing</methodName>
<params>
<param><value><string>ブログの名前</string></value></param>
<param><value><string>ブログのURL</string></value></param>
<param><value><string>RSSのURL</string></value></param>
</params></methodCall>”

string(26) “weblogUpdates.extendedPing”

array(3) {
[0]=>
string(13) “ブログの名前”
[1]=>
string(21) “ブログのURL”
[2]=>
string(31) “RSSのURL”
}

string(109) “<?xml version=”1.0″ encoding=”utf-8″?>
<params>
<param>
<value>
<int>1</int>
</value>
</param>
</params>

コメントする