レスポンスヘッダに"Content-Encoding: deflate"とある場合、HTTP_Requestはデコードしない模様。
Request #11246 Problem with deflate encoding
HTTP_Requestは、リクエストヘッダのContent-Encodingを探し、その値がgzipだった場合に自動的にデコードしてくれます。ところが、"Content-Encoding: deflate"の場合にはデコードしてくれません。ソースを読む限り、gzip圧縮の判定を「Content-Encodingの値がgzipである場合」としており、それ以外についてはどこにも記述されていません。deflateは無視しているようです。
gzipのデコードは_decodeGzipメソッドで行われます。PHPにはgzinflate関数が用意されており、_decodeGzipメソッドでも伸長処理にはこれを使っています。ただし、RFC1952に従ったパース処理などを行ってから、gzinflate関数を実行します。このため、deflateのデコードを_decodeGzipメソッドで行うのは駄目っぽいです。
- RFC 1951 DEFLATE Compressed Data Format Specification version 1.3 日本語訳 - futomi's CGI Cafe
- RFC 1952 GZIP file format specification version 4.3 日本語訳 - futomi's CGI Cafe
ひとまず、deflateの場合はgzinflate関数で伸長するようにしてその場をしのいでおきます。
Zend_Http_Response::decodeDeflateでは、gzuncompress関数を使っているようです。一方で、Zend_Http_Response::decodeGzipではgzinflate関数を使ってるのはなぜでしょうか。やはり、deflate圧縮とgzip圧縮について深追いしないと駄目でしょうか。
PHPのドキュメントに、「HTTPサーバの言うdeflateとPHPの言うdeflateは違う」というようなことが書いてありました。
Take care that that "PHP deflate" != "HTTP deflate".
The deflate encoding used in HTTP is actually zlib encoded.
This is what PHP functions return:
gzencode() == gzip
gzcompress() == zlib (aka. HTTP deflate)
gzdeflate() == *raw* deflate encoding
PHP: gzdeflate - Manual
RFCを見てみると、なんだかんだでzlibとの事。つまり、PHPのgzuncompress関数を使うのが正しい模様。
The "zlib" format defined in RFC 1950 [31] in combination with the "deflate" compression mechanism described in RFC 1951 [29].
RFC 1951 [29] に記述されている "deflate" 圧縮メカニズムと結合した、RFC 1950 [31] にて定義されている "zlib" フォーマット。
ハイパーテキスト転送プロトコル -- HTTP/1.1
(gzinflate関数で解決できた)URLについてgzuncompress関数を使うようにしたところ、gzuncompress関数がfalseを返しました。とりあえず、gzuncompress関数→gzinflate関数という体制でやっておくことにしてみます。
また別のURLについて試したところ、gzuncompress関数で正しく処理され、gzinflate関数でfalseとなりました。サーバによってはdeflateのデータフォーマット(?)が違うようですね。


コメントする