Yuriko.Net 個別記事

チャンク形式の HTTP 返答に対応する
Ktai Style 1.41 をリリースすべくテストを重ねていますが、細かいバグが少しずつ発見されてしまい、それを修正してはまたテストする、というサイクルに陥っています……。1.3x 系統がバギーだっため、その尻拭いという状況ですね で、今日は「外部サイトのリンクをクリックしたとき、携帯サイトの検出時に不正な URL を拾ってしまう」という現象を発見しました。具体的には、「ひたちなか海浜鉄道が WordPress 採用」で、http://finder.music.coocan.jp/?p=152 へのリンクをクリックしたとき「http://finder.music.coocan.jp/?p=15224http://finder.music.coocan.jp/?p=1525」にジャンプしようとしました。http:// がダブっているのは、検出した URL が相対 URL であったとき、飛び先の URL をベースとして補完したためです。つまり、携帯サイトとして検出した URL 自体は「24http://finder.music.coocan.jp/?p=1525」でした。
これはとっても不可思議なので、redir.php をいじって実際に受信したデーターを見てみました。すると、以下のような内容だったのです。
fa <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head profile="http://gmpg.org/xfn/11"> <meta http-equiv="Content-Type" content=" 9 text/html a ; charset= ……中略…… 2e <link rel="alternate" media="handheld" href=" 24 http://finder.music.coocan.jp/?p=152 5 " />
実際のデーターの前にバイト数がくっついた形式になっています。はて、PHP の fgets()
はこんな形式になったっけ、と思ったのですが、よく調べると、これは HTTP のチャンク形式のデータなのでした。RFC2616に詳しく書かれていますが、とほほの WWW 入門の解説がシンプルで分かりやすいでしょう。
このサーバーはえらく細切れにデーターを返していて、肝心の rel=”altinate” media=”handheld” の URL 部分の前後でチャンクが切れてて、バイト数が挟まってしまっていたのです。その結果、「24http://finder.music.coocan.jp/?p=1525」が携帯サイトの URL であると検出していました。数回リトライしてもほぼ同じ結果です。なお、たいていのサーバーでは 1024 バイトぐらいは一括して返してくるので、こういう現象はめったに起きません。
redir.php のコードは、wp-includes/comment.php の discover_pingback_server_uri()
を参考にしていますが、このコードがチャンク形式を考慮していないため、今回の現象が発生しました。対応させるためには、HTTP ヘッダで「Transfer-Encoding: chunked」の有無を確認し、あれば「バイト数・コンテンツ」のペアで受信させることが必要になります。WordPress コアの不具合なので、trac にも報告(#7224)しておきました。添付ファイルを2回送ってしまったのはちょっとしたミスです
これで、携帯サイトの検出も問題なくできるようになりました。もうちょっとテストしたいので、Ktai Style 1.41 のリリースは金曜日ぐらいかな〜〜。
[追記] trac のコメントで「HTTP/1.0 ならばチャンク形式がないので、リクエスト自体を HTTP/1.0 にすればよいのでは」という提案がされています。そういう手もあるかと思いますが、それでいいのかな??