2008年7月02日の投稿

2008-07-02
晴れ

チャンク形式の HTTP 返答に対応する

ゆりこ による 23:55:58 の投稿
カテゴリー: WordPressハック,ネットワーク
タグ: , ,

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 にすればよいのでは」という提案がされています。そういう手もあるかと思いますが、それでいいのかな??