19時35分00秒 [C++ Builder]
煮詰まった…。久しぶりに。
解決までに数時間は悩んだ気がしますよ。
HTTP-POSTで特定のサーバにデータを投げるプログラムを書いたんですけど、C++ BuilderのNMHTTPコンポーネントを使ったら、思わぬところで煮詰まっちゃいました。
具体的には、RSS・Atomフィード作成ソフト「Fumy RSS & Atom Maker」に、Update Ping送信機能を加えようとしたんですが。
ブログ向け検索サイトなどでは、各ブログから「更新したよー」という情報(Update Ping)を受け取るためのPingサーバというのを設置しています。
Movable Typeなどのブログツールでは、それらがUpdate Pingの送信まで行ってくれるので何も気にする必要はないのですが、自力でRSSを作成した場合は、Pingの送信も自力で行う必要があります。
「Fumy RSS & Atom Maker」では、作成したRSS・AtomフィードをFTPでサーバにアップロードするところまではサポート済みなので、次に、Update Pingを送信できる機能を加えたいと思っていたのです。
で。ここら辺からが本題ですが。(^^;)
まず、Update Pingを送信するためには、HTTPでサーバと通信しないといけません。まあ、HTTPを使ってWebサーバから何か情報を引っ張ってくる(ダウンロードする)のは、そんなに難しい話ではありません。特に、APIとか開発環境のコンポーネントとか使えば、「HTTP(Hyper Text Transfer Protocol)」自体について何の知識が無くてもプログラミングできちゃいます。(^^;)
で、Update Pingは、XML-RPCというプロトコルを使って HTTP-POST でPingサーバに情報を送る必要があります。情報と言っても、Webサイト名とURLの2つだけなのですが。XML-RPCの仕様に従って記述してやる必要があるものの、それはただその仕様に従ってテキストデータを作ればいいだけなので問題はありません。
ここで問題になったのは(煮詰まったのは)、HTTP-POSTでサーバと通信するところ。^^;
C++ Builderのコンポーネントである「TNMHTTP」を使ったので、基本的にはかなり楽なはずです。プロトコルについて知らなくても、簡単に通信プログラムを書けちゃいます。
実験として、任意のWebサーバから、GETでHTMLをダウンロードしてくるプログラムはうまく機能しました。GETで通信ができたんなら、POSTもできるでしょう。(^^;)
NMHTTPコンポーネントを使う場合、
とか書いていたのを、
と書いてやれば済みます。
で、実際にサーバと通信させてみたところ、HTTP的には通信は完了しているのですが、Pingサーバとの会話という点では失敗してしまいます…。
具体的には、Pingサーバからは、次のような返事が返ってきます。
Application failed during request deserialization: not well-formed at line 1...
サーバからは、200 OK の返事が来るんですけど、成立したHTTP-POSTで送った内容に問題があるので、Update Pingは成功しないのですね…。
エラーの内容からして、送ったXMLが「Well-formedではない」ということらしいです。
でも、送ったXMLは、XML-RPCの仕様に従って記述したもので、XML ValidatorとかでチェックしてもXMLの文法的に問題はないものです。
ここで、煮詰まりました…。(^^;;;
ずいぶん…。
とにかく、送ってるXMLは間違ってないはずなので、送る方法に問題があるのだろうか…と思って、いろいろ試行錯誤してたんですが、結局、具体的にサーバに対してどんな文字列を送ってるのかを確認しないことにはどうしようもない、という結論に達しました。
そこで、AN HTTPDを使って、ローカルにWebサーバを立てて、そこに対してPOSTしてみることにした…のですが、POSTされてきたデータの受け皿になるCGIとかがないとエラーになるし、そもそも、HTTPヘッダのログまでは取れなさそうだったので、その方法は断念。
やはり、ネットワークを流れるパケットを見るしかないか…、ということで、パケットキャプチャソフトを起動。(^^;)
通信した瞬間のパケットを全部キャプチャしてみました。
すると!
なんと、「<?xml version="1.0"?>」で始まる一連のXMLが、全部、「%3C%3Fxml+version%3D%221%2E0%22%3F%3E」みたいにエンコードされてましたっ。(^^;;;
XMLのタグとか引用符とかを全部エンコードして送信しちゃってるから、XMLとして解釈されないということだったわけです。^^;
サーバ側からこちら側へ届くエラーもXML形式のデータなんですが、それは、ちゃんと余計なエンコードとかされずに、XMLで届いてました。
やはり、直接自力でサーバと対話するプログラムではなく、コンポーネントに頼ると、こういう問題が起きちゃうのですね。^^;;; 具体的にサーバとどんな対話してんのかが簡単には分からないわけで。
で、結局、NMHTTPコンポーネントのPostメソッドに、送信文字列を直接指定するのではなく、送信文字列を格納したファイルパスを指定することで、解決しました。
NMHTTPコンポーネントのOutputFileModeプロパティを「true」にすると、Postメソッドの第2引数に、送信する文字列を格納したファイルパスを指定できるようになります。そうすると、ファイルの中身をそのまんま送信してくれました。
これで、無事に Update Ping の送信が成功しました。^^;;;
長かった…。
これだけで、今日1日費やしちゃったよ…。
試行錯誤のすべてを書いたわけではないので、文章にすると短いけど。^^;;;
まあ、とりあえず、無事にUpdate Pingの送信には成功したので、あとは、「Fumy RSS & Atom Maker」用のUpdate Ping送信機能として実装するだけです。
この日記へのコメントはお気軽に! コメント数:1件
コメント数: 1件
初めまして。たんぽぽと申します。
PINGについて自分で勉強中ですので知識が足りないけど、
アドバイスで何か、教えて頂ければ幸いと思います。
これからよろしくお願いします。
投稿者 たんぽぽ : 2008年04月22日 23:07