金箱 遼

2012.04.04

不正なContent-Encodingヘッダを受け取ることもあるという話

こんにちは。アライドアーキテクツの金箱(かねばこ)です。

アライドアーキテクツではモニプラの開発&運用を担当しています。どう作るかより何を作るかを考えるのが好きなエンジニアです。

先日解決した問題について、将来的にもまれに出会いそうなケースだったため、備忘も含めてエンジニアブログのほうに書きます。

問題について

先日、FC2ブログのRSSが取得できないという問題に出会いました。

現象はブラウザでRSSを確認するときちんと見れているのに、プログラムでRSSを読むときにどこかでエラーが起きて取得できないというものでした。

デバッグを行っていろいろさかのぼっていくと、どうやらHTTPレスポンスをデコードしているところでおかしなことになっているぞと分かりました。以下その原因について書いていきます。

 

HTTPとそのエンコーディングについて

RSSの取得は、HTTPプロトコルでやりとりしています。HTTPプロトコルでのやりとりは、HTTPレスポンスヘッダをクライアントサイドのプログラムで作成して、取得したい先のwebサーバーにリクエストして行っています。

今回のRSSの取得では、ヘッダにはAccept-Encodingフィールドにidentityをセットしていました。

webサーバーにAccept-Encodingフィールドをセットしたリクエストを投げると、サーバーはセットされたエンコーディングでレスポンスを返します。Accept-Encodingフィールドはカンマ区切りで複数指定可能なので、サーバーはその中からエンコーディングを選んでレスポンスを返します。

実際にレスポンスで返したエンコーディングは、Content-Encodingフィールドに明記してくれています。クライアント側では、このContent-Encodingフィールドの情報をもとに、レスポンスをデコードして幸せになるというわけです。

もし、サーバーがAccept-Encodingフィールドにセットされたエンコーディングでレスポンスを返せない場合は、406ステータスコードを返す決まりになっています。

ちなみにコーディングの種類はこちらが分かりやすいです。( http://www.studyinghttp.net/body#Codings

 

今回のケース

FC2ブログのRSSを取得しようとAccept-Encodingフィールドにidentityのみをセットしてリクエストを投げたところ、レスポンスのContent-Encodingフィールドにdeflateが入ったレスポンスが返って来ていました。

(この時点でややおかしいです。)

deflateは「ZLIB データ圧縮フォーマットですよ」という意味なので、プログラムがデコードを試みます。

ところが、ヘッダではdeflateですよとなっているものの、ボディーは無圧縮状態のものが入っていたために、デコードに失敗してエラーとなっていました。

今回のケースではつまり、RSSの取得に失敗ということです。

 

調査と解決

興味半分でいろいろ試してみたところ、gzipをセットした場合などはidentityで返ってきたりもしてました。

Googleで同じような事例を探してみたところ、今から2年ほど前からチラホラいるように見受けられました。

原因が分かったため、HTTPレスポンスをContent-Encodingをもとにしてデコードする箇所で、もしうまくデコードできなかった時にはContent-Encodingを疑って別のパターンを試みるという方法で回避しました。

もし似たようなケースに直面した方がいれば、エンコーディングを疑ってみるのも一つの道筋だと思います。

参考にさせて頂いたサイト:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3

 

 

最後に

アライドアーキテクツでは、一緒に働く仲間を随時募集しています。是非一度採用サイトを覗いてみてください。お待ちしております。