こんにちは。アライドアーキテクツの金箱(かねばこ)です。
アライドアーキテクツではモニプラの開発&運用を担当しています。どう作るかより何を作るかを考えるのが好きなエンジニアです。
先日解決した問題について、将来的にもまれに出会いそうなケースだったため、備忘も含めてエンジニアブログのほうに書きます。
問題について
先日、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
最後に
アライドアーキテクツでは、一緒に働く仲間を随時募集しています。是非一度採用サイトを覗いてみてください。お待ちしております。
サービスのことを考えることと、グロースを考えることが大好きです。 どんどん世の中が便利になってうれしいです。 どうぞよろしくお願いします。