XML-RPC で "Premature end of file."
Java で XML-RPC の開発をしている。
動作確認は UNIX コマンドの curl で手軽にすませているのだが、突然、すべての curl コマンドで Premature end of file. というエラーが出るようになった。
[Fatal Error] :-1:-1: Premature end of file.
このエラーには見覚えがある。たしか、XML の絡んだ通信で接続状態が悪くなり、通信が途絶えた場合などに ぼろぼろ出ていたやつだ。つまり、XML が不完全なのだろう。
しかし、curl の POST で送っているデータをいくら調べてもおかしい部分が見つからない。 問題になりがちな改行を取り除いても、コンソールのエンコーディングを変更しても同じ。
しかたがないので、デバッガでブレークポイントを設定し、動作を追ってみた。
その結果、リクエストオブジェクトの入力ストリームから読み出す時点でデータが空なことが判明。つまり、curl で POST したデータを読みだせていないわけだ。
では、何が原因でデータを読みだせていないんだろう? curl の -v オプションの出力を眺めているうちに気がついた。
POST /api/xmlrpc HTTP/1.1
User-Agent: curl/7.13.1 (powerpc-apple-darwin8.0) libcurl/7.13.1 OpenSSL/0.9.7l zlib/1.2.3
Host: example.com
Pragma: no-cache
Accept: */*
Content-Length: 123
Content-Type: application/x-www-form-urlencoded
application/x-www-form-urlencoded で POST しているせいだ。
Content-Type が application/x-www-form-urlencoded だと、HttpServletRequest がパラメータとして解析するために先に入力を読みだしてしまうので、HttpServletRequest#getInputStream() から読みだすときは空なわけだ。
次のように POST すれば、正常に動作した(--data-ascii の XML は省略)。
% curl -v -H "Content-Type: text/xml" --data-ascii "..." "http://example.com/api/xmlrpc"
どうやら、昨日まではちゃんと -H オプションで Content-Type を指定していたのだが、一日寝ると忘れてしまったようだ。
だから、ブログに書いている。
Apache XML-RPC への不満
Apache Web Services Project の一環として開発されている Apache XML-RPC は Web に紹介記事も多く、もっとも利用されている印象を受ける。
実際、これまで仕事でも XML-RPC クライアントとして Apache XML-RPC を使用していた。他の選択肢を知らなかった、というのもあるが、Apache というブランドの影響も大きいと思う。
しかし、不満がないわけではない。
特に、クラス階層が複雑なのには手こずった。動作をカスタマイズしたいときなど、あるクラスがどのインターフェースを実装し、どのファクトリで生成されるかを調べるだけでも大変だ(RequestProcessorFactoryFactory インターフェースまでくると、もう冗談のように思えてくる)。
実例をあげよう。
RPC の結果として不正な XML が返ってきた場合のエラー処理。 たとえば、XML 宣言の前に PHP のエラーが出力されている、なんてことはざらにある(現実とはそういう世界なのだ)。こういうときでも、XML 宣言以降は正当な XML なので、できるだけ XML をパースして処理の結果を拾いたい。
そして、このリカバリ処理自体は難しくない。例外をキャッチして、結果の文字列を XML 宣言までスキップして、再度パースしてみるだけだ。
だが、結局、その処理をするためには、ダウンロードした Apache XML-RPC のソースコードから既存のクラスをコピーして別のクラスを作成する必要があった。どうしてだろう? もしかすると、他にエレガントな解決方法があったのかもしれない。だが、発見できなかった。
そして、いま、サーバサイドの XML-RPC サービスを実装しているのだが、今度は出力エンコーディングを設定する方法が分からない。きっとどこかで、エレガントな解決方法が、発見されるのを待っているのだろう。
ブログの XML-RPC サポート
個人的メモとして、各ブログの XML-RPC サポート状況をまとめてみた。
Movable Type は Blogger の API と、米 UserLand Software 社の MetaWeblog API に準拠しているようだ。また、WordPress も Movable Type に準ずるかたちになっている。
面白いのは Blogger。 現在は XML-RPC ではなく、 Google Data APIs (GData) による Blogger Data API を使用している。
Web ページのサイドバーには他にも "Calendar Data API" や "Spreadsheets Data API" など、Google の他サービスの名前が並んでいるので、GData はこれらのサービスでも実装されているのだろう。GData によるサービス同士の連携もあるのかもしれない。
Apache XML-RPC のファイル名
Apache XML-RPC で 配布されている .jar は依存ライブラリを除くと 3 つあるのですが、
- xmlrpc-client-3.0.jar
- xmlrpc-common-3.0.jar
- xmlrpc-server-3.0.jar
ファイル名を Mac の Finder からエディタにコピペして気づいた。
xmlrpc-client-3.0.jar xmlrpc-common-3.0.jar xmlrpc-server-3.0.jar
すべて文字数が一緒なんです。
