Вопрос по apache, cgi, internet-explorer-8, compression, c++ – Internet Explorer 8 + Deflate

5

У меня очень странная проблема. Я действительно надеюсь, что у кого-то есть ответ, потому что я не знаю, где еще спросить.

Я пишу CGI приложение на C ++, которое выполняется Apache и выводит HTML-код. Я сам сжимаю вывод HTML - из моего приложения C ++ - поскольку мой веб-хост по какой-то причине не поддерживает mod_deflate.

Я проверил это с Firefox 2, Firefox 3, Opera 9, Opera 10, Google Chrome, Safari, IE6, IE7, IE8, даже Wget .. Он работает сANYTHING кроме IE8.

IE8 просто говорит «Internet Explorer не может отобразить веб-страницу» без какой-либо информации. Я знаю это из-за сжатия только потому, что оно работает, если я его отключаю.

Вы знаете, что я делаю неправильно?

Я использую zlib, чтобы сжать его, и точный код:

    /* Compress it */
int compressed_output_size = content.length() + (content.length() * 0.2) + 16;
char *compressed_output = (char *)Alloc(compressed_output_size);
int compressed_output_length;
Compress(compressed_output, compressed_output_size, (void *)content.c_str(), content.length(), &compressed_output_length);

/* Send the compressed header */
cout << "Content-Encoding: deflate\r\n";
cout << boost::format("Content-Length: %d\r\n") % compressed_output_length;
cgiHeaderContentType("text/html");
cout.write(compressed_output, compressed_output_length);


static void Compress(void *to, size_t to_size, void *from, size_t from_size, int *final_size)
{
int ret;
z_stream stream;

stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;

if ((ret = deflateInit(&stream, CompressionSpeed)) != Z_OK)
    COMPRESSION_ERROR("deflateInit() failed: %d", ret);

stream.next_out = (Bytef *)to;
stream.avail_out = (uInt)to_size;
stream.next_in = (Bytef *)from;
stream.avail_in = (uInt)from_size;

if ((ret = deflate(&stream, Z_NO_FLUSH)) != Z_OK)
    COMPRESSION_ERROR("deflate() failed: %d", ret);

if (stream.avail_in != 0)
    COMPRESSION_ERROR("stream.avail_in is not 0 (it's %d)", stream.avail_in);

if ((ret = deflate(&stream, Z_FINISH)) != Z_STREAM_END)
    COMPRESSION_ERROR("deflate() failed: %d", ret);

if ((ret = deflateEnd(&stream)) != Z_OK)
    COMPRESSION_ERROR("deflateEnd() failed: %d", ret);

if (final_size)
    *final_size = stream.total_out;
return;
}
Какие-нибудь подсказки в заголовке Accept-Encoding в IE8? John Kugelman
Похоже, пришло время выполнить обнаружение агента пользователя. Да, это отвратительный взлом, но в моем ограниченном опыте веб-разработка полна ими. j_random_hacker
cout & lt; & lt; boost :: format (& quot; Content-Encoding:% s \ r \ n & quot;)% ((UserAgent.GetBrowser () == INTERNET_EXPLORER & amp; UserAgent.GetVersion () & gt; = 8)? & quot; gzip & quot; & Quot; выкачать & Quot;); // Хорошо, это исправляет. Все еще ищу реальный ответ, хотя, если кто-то может придумать один. Andreas Bonini
После дополнительных попыток ... Если я отправляю кодировку контента как gzip (он не! Он дефлятирует), он работает в Internet Explorer только в любой версии, включая ie8, тогда как он не работает ни в одном другом браузере. Если я отправлю дефлат, правильный, он будет работать в любом браузере, включая ie6 и ie7, но не на ie8 & lt;. & Lt; Andreas Bonini
хорошо это странно Если я отправлю "gzip" как кодировка содержимого, она работает в IE8, но в любом другом браузере ..: Ошибка кодировки содержимого Невозможно отобразить страницу, которую вы пытаетесь просмотреть, поскольку она использует недопустимую или неподдерживаемую форму сжатия. Andreas Bonini

Ваш Ответ

2   ответа
5

что я обнаружил в этом, поскольку я написал свой собственный алгоритм дефляции, мой собственный HTTP-сервер и, к моему ужасу, IE8 также не смог распознать мой дефлированный контент:

HTTP RFC - этоhttp://www.faqs.org/ftp/rfc/rfc2616.pdf, Страница 17 гласит, что RFC 1950 и RFC 1951 используются при выполнении дефляции в заголовках HTTP. RFC 1950 просто определяет заголовок и трейлер байтов; алгоритм дефляции определен в RFC 1951. Когда я запрограммировал это в спецификации, IE8 не удалось.

Когда я проигнорировал RFC 1950 и только сделал RFC 1951, это прошло.

Я бы тогда предположил, что IE8 неправильно следует RFC 2616 стр. 17, и все остальные браузеры достаточно хороши, чтобы принять любой формат.

Я только что наткнулся на прокси-сервер веб-кэширования клиента, который принудительно запускает дефляцию, и угадаю, какую реализацию они выбрали? Не тот, вероятно, для поддержки IE8. К сожалению, наш Java-клиент, использующий стандартные HTTP-библиотеки, ожидает правильной реализации deflate. Мне придется отключить поддержку deflate в нашем клиенте и заставить их использовать gzip или ничего.
5

но есть некоторые тонкие различия с заголовком, поэтому, если вы измените кодировку контента, вы должны также изменить свои параметры на метод кодирования (в частности, Размер окна)!

Увидеть:http://apcmag.com/improve_your_site_with_http_compression.htm

Возможно, другие браузеры игнорируют вашу спецификацию кодировки контента и выполняют некоторое автоматическое распознавание, но IE8 не ...

Увидеть:http://www.zlib.net/manual.html#deflateInit2

Попробуй использовать:

method=Z_DEFLATED
windowBits=-15  (negative so that the header is suppressed)

И используйте & quot; gzip & quot; как контент-кодировка

+1, отличная находка! Представьте себе, ошибка в mod_gzip.
Вау, спасибо! Я люблю тебя: D Небольшое исправление, хотя. Существует 3 (!) Формата сжатия: zlib - тот, который я использовал, который, как мне показалось, был & quot; deflate & quot; -, спустить и GZIP. Как будто это не было достаточно запутанным, все 3 из них, очевидно, созданы с использованием библиотеки zlib. Если не указать, что windowBits (как я делал) выводит формат zlib, используя отрицательное значение (как вы предложили), выдаетDEFLATED формат (не gzip!). Я пока не уверен, как вывести формат gzip (и мне все равно, теперь он работает с deflate во всех браузерах). ЕЩЕ РАЗ СПАСИБО!! :) Andreas Bonini

Похожие вопросы