アットウィキロゴ

XML-RPC

XML-RPC 2010-06-09



An XML-RPC message is an HTTP-POST request. The body of the request is in XML. A procedure executes on the server and the value it returns is also formatted in XML.

なるほど。

Procedure parameters can be scalars, numbers, strings, dates, etc.; and can also be complex record and list structures.

こういうときのscalarとは何を指すのやら。
数値型、文字列型、日付、それに構造体やリスト構造が使えるようだ。

The format of the URI in the first line of the header is not specified. For example, it could be empty, a single slash, if the server is only handling XML-RPC calls. However, if the server is handling a mix of incoming HTTP requests, we allow the URI to help route the request to the code that handles XML-RPC requests. (In the example, the URI is /RPC2, telling the server to route the request to the "RPC2" responder.)

URIの最初の行の書き方は特に決まっていないので、からっぽでもいいらしい。
でも、XML-RPCとしてサーバに扱ってもらいやすいように/RPC2と書いておくといいことがあるようだ。

A User-Agent and Host must be specified.
The Content-Length must be specified and must be correct.

User-AgentとHostは必須。Content-Lengthは必須かつ正しくないといけないらしい。

The payload is in XML, a single <methodCall> structure.

当たり前だけれどメソッドの呼び出しは1リクエスト1回。

The <methodCall> must contain a <methodName> sub-item, a string, containing the name of the method to be called. The string may only contain identifier characters, upper and lower-case A-Z, the numeric characters, 0-9, underscore, dot, colon and slash. It's entirely up to the server to decide how to interpret the characters in a methodName.

メソッド名につかえるキャラクタは[A-Z0-9_.:/]
サーバ側は全部受信してから解釈する。

For example, the methodName could be the name of a file containing a script that executes on an incoming request. It could be the name of a cell in a database table. Or it could be a path to a file contained within a hierarchy of folders and files.

methodNameというのは、スクリプトのファイル名だったり、databaseのセル名だったり、ファイルやフォルダパスだったりするらしい。

If the procedure call has parameters, the <methodCall> must contain a <params> sub-item. The <params> sub-item can contain any number of <param>s, each of which has a <value>.

methodCallはparamsを持っていて、paramsはたくさんparamを持っていて、paramはvalueを持っている。
methodCall -> params -> param1, param2, ...;
param -> value;

Scalar<value>s


Tag Type
<i4> or <int> 4byteの符号付き整数
<boolean> 0(false) or 1(true)
<string> 文字列
<double> 浮動小数
<dateTime.iso8601> 日時
<base64> base64でエンコードされたバイナリ

Typeを指定しない場合はstringを表す。
バイナリが送れるのか。

<struct>s

構造体はmemberを持ち、各々のmemberはnameとvalueを持つ。

<struct>
  <member>
    <name>ID</name>
    <value><i4>21</i4></value>
  </member>
  <member>
    <name>name</name>
    <value><string>ISONO Katuo</string></value>
  </member>
</struct>

構造体に構造体や配列とのネストも可能。
つまり、valueの種類は自由。

<array>s

配列はdataを持ち、dataはたくさんのvalueを持つことができる。

<array>
  <data>
    <value><i4>1</i4></value>
    <value><string>Hello World!!</string></value>
    <value><double>3.141925</double></value>
  </data>
</array>

構造体や配列とのネストも可能。

Response format

  • HTTPステータスコードは200を返せばおk
  • Content-Typeはtext/html
  • Content-Lengthは正確に
  • bodyは一つのXML構造体<methodResponse>

<methodResponse>はfaultを含んでいることがある。
faultは一つのvalueを持ち、valueは一つの構造体で、<faultCode>と<faultString>の二つの要素を持つ。
<faultCode>の型は<int>で、<faultString>の型は<string>である。
<methodResoponse>はfaultかparamsのどちらか一方しか持つことができない。

試しに使ってみる

XML-RPCで実装されているAPIとしてはてなキーワード連想語APIを使ってみたい。
環境は、Apache2 on Ubuntu and PHP5ということで、PHPでXML-RPCを扱うパッケージをインストールする。
調べると、PEARのXML-RPCというのに当たったが、Python風に、よりシンプルに扱えるように作り直されたXML-RPC2が新たにでているようだ。(XML-RPC2はPHP5限定)
PEARが入っていなかったので、まずはPEARをインストール。
sudo apt-get install php-pear
続いて、PEARのパッケージマネージャから、
sudo pear install -a XML_RPC2
としたが、php extensionでcurlがいるよと怒られる。
ではしかたないと、curlをインストール。
sudo apt-get install php5-curl
php -m
extensionsの一覧にcurlが追加されていたらインストールは成功。
そうしたら、あらためて、
sudo pear install -a XML_RPC2
以上で、環境設定は終了。

補足

pearのインストーラーのバージョン自体が低くて、XML_RPC2がインストールできないことがあるので、そのときは、
sudo pear upgrade pear-1.5.4
とすると解決。

実装

ほぼPEARのマニュアルサンプルと一緒です。

<html>
 <head>
 <title>Hatena API Test</title>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 </head>
 <body>
 <?php
    require_once 'XML/RPC2/Client.php';
    $prefix = 'hatena.';
    $encoding = 'utf-8';
    $uri = 'http://d.hatena.ne.jp/xmlrpc';
    $methodname = 'getSimilarWord';  
    // defaultのencodingはiso-8859-1っぽいので、明示的に指定
    $options = array(
        'prefix' => $prefix,
        'encoding' => $encoding
    );
    // XML_RPC2_Client オブジェクトを作成します(バックエンドを指定していないので、
    // もし使用可能なら XMLRPCEXT を使用します (これが使用できなければ PHP を使用します))
    $client = XML_RPC2_Client::create($uri, $options);
 
    try {
        /* JSON形式でいうとこういう感じの引数を渡します
        {   wordlist : [ "keyword1", "keyword2", "keyword3" ] }
        */
        $result = $client->$methodname(array(wordlist => array('Perl', 'Ruby', 'PHP', 'Python')));
 
        // $result は PHP の型になっています (XMLRPC のデコードは不要で、すでにデコード済みです)
        /* JSON形式でいうとこういう感じのレスポンスが返ってきている
        {   wordlist : [
                        {   word : "word1" },
                        {   word : "word2" },
                        {   word : "word3" }
                        ]
        }
        */
        $result = $result['wordlist'];
        foreach($result as $value) {
            print("${value['word']}<br>\n");
        }
    } catch (XML_RPC2_FaultException $e) {
        // XMLRPC サーバが XMLRPC のエラーを返しました
        die('Exception #' . $e->getFaultCode() . ' : ' . $e->getFaultString());
    } catch (Exception $e) {
        // その他のエラー (HTTP あるいはネットワークの問題など...)
        die('Exception : ' . $e->getMessage());
    }
 ?> 
 

補足

methodを呼び出した後に、うんともすんともいわなくなる症状(XML_RPC2 を使用して、、、)に見舞われることがある。しかも、パケットを覗いてみるとサーバからのレスポンスは正常に返ってきている……というような状況である。
そのときは、php-xmlrpcをインストールすれば治る。centOSでやっていたらこの症状に悩まされ、ざっと、4時間が溶けた。

参考資料


-
最終更新:2010年06月09日 10:22