Для комментариев зарегистрироваться или войти
Либо используйте ваш Open_ID, например аккаунт гугл, яндекс или ЖЖ
 

10 апреля 2009 :Про Gzip и магическое число 10

Технологи фирмы где я работаю иногда делятся со мной своими заметками, вот одна из них.

Не так много людей (не только разработчиков, а вообще), которые знают о том что сайты могут сжимать данные для экономии траффика, методом Gzip. Ещё меньше тех кто для той же экономии траффика решил программно скачивать (на PHP например) страницы именно в этом формате. И на этом начинается интересное.

Допустим мы скачиваем яндекс, его интересней всего конечно, например заглавная страница:
http://web-sniffer.net/?url=http%3A%2F%2Fwww.yandex.ru%2F&gzip=yes
которая выдаёт заголовок Content-Encoding:gzip
Content (encoded: 13.27 KiB / decoded: 35.57 KiB) - контент в 3 раза сжат gzip'ом

Допустим я умею делать socks запросы, скачивать страницу, в том числе методом chunked и получать body документа в $data.
сделав echo gzinflate($data); (функция gzuncompress делает то же самое, рекомендуется использовать gzinflate)
в итоге ловим

Warning:  gzinflate(): data error in ***

Изучив мануалы, находим крайне полезные замечания (на английском)
"Согласно спецификации, CRC32 контрол сумм, блабла, а надо

Adler-32, который ожидает PHP.

поэтому надо править так

function gzuncompress_crc32($data) {
$f = tempnam('/tmp', 'gz_fix');
file_put_contents($f, "\x1f\x8b\x08\x00\x00\x00\x00\x00" . $data);
return file_get_contents('compress.zlib://' . $f);
}

ну, как можно предположить
Warning: gzinflate() блабла

Читаю форумы и юзер контрибутед нотисе дальше
"вы все ламеры, совершенно понятно что заголовок надо обрезать (те самые \x1f\x8b кстати)
$result = gzinflate(substr($compressedData, 2))"

Warning: gzinflate() блабла

And when retrieving mod_deflate gzip'ed content and using gzinflate() to decode the data, be sure to strip the first 11 chars from the retrieved content.
$dec = gzinflate(substr($enc,11));"

написан видимо тем же человеком, но уже в другом месте.
ну... как следствие Warning: gzinflate() блабла

Ну, читаем дальше

When retrieving mod_gzip'ed content and using gzinflate() to decode the data, 
be sure to strip the first 10 chars from the retrieved content.
$dec = gzinflate(substr($enc,10));

(что в переводе значит "2 байта отстой и не работает, надо обязательно отрезать 10 байт!")
Warning: gzinflate() блабла

Большинство комментариев в багтреке пхп идут в духе "да вы батенька хидеры-то наверное не отрезали от реквеста, вот и дурак"
Покопавшись ещё с полчасика, и поскачивав исходники разных HTTP-Request классов, обнаружил ещё 2 упоминания числа 2 и 10.

Написав волшебное заклинание:

for($i=10;$i<20;$i++)
echo $i.@gzinflate(substr($data,$i));
die();

я обнаружил что работает только echo gzinflate(substr($data,10)); на чём и заканчиваю историю

Прогноз погоды: число 10 - сегодня хорошее число чтобы скачать gzip. =)

P.S. итоге у меня первые 10 символов были с кодами 31,139,8,0,0,0,0,0,0,3, которые нужно всегда отрезать, а до этого как нетрудно догадаться 13,10,13,10 - двойной перевод строки который отделяет хидеры от тела документа.

 


я буду очень признательна если вы прокоментируете эту статью

Комментарии:


Чтобы оставить комментарий нужно зарегистрироваться или войти.
Либо волшебно используйте ваш логин в Google, Яндекс, рамблер или ЖЖ чтобы войти через Open_ID
Оставить комментарий как:
Гость:
Сообщение:
Подпишитесь на статьи через RSS

15 самых популярных статей: