Pregunta sobre c++, apache, internet-explorer-8, cgi, compression – Internet Explorer 8 + Deflate

5

Tengo un problema muy raro ... Realmente espero que alguien tenga una respuesta porque no sabría dónde preguntar.

Estoy escribiendo una aplicación cgi en C ++ que es ejecutada por Apache y genera código HTML. Yo mismo estoy comprimiendo la salida HTML, desde dentro de mi aplicación C ++, ya que mi servidor web no admite mod_deflate por alguna razón.

He probado esto con Firefox 2, Firefox 3, Opera 9, Opera 10, Google Chrome, Safari, IE6, IE7, IE8, incluso wget ... Funciona conCUALQUIER COSA excepto IE8.

IE8 simplemente dice "Internet Explorer no puede mostrar la página web", sin información alguna. Sé que es debido a la compresión solo porque funciona si lo inhabilito.

¿Sabes lo que estoy haciendo mal?

Uso zlib para comprimirlo, y el código exacto es:

    /* 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;
}
Parece que es hora de realizar la detección de agente de usuario. Sí, es un truco feo, pero en mi experiencia limitada el desarrollo web está lleno de ellos. j_random_hacker
Envía tanto deflate como gzip como Accept-Encoding. Verifico si contiene "desinflar" antes de enviar cualquier salida desinflada. Thomas Bonini
Además, asegúrese de haber leído esta pregunta SOstackoverflow.com/questions/388595/…. Mejor quedarse con gzip. Eye
cout << boost :: format ("Content-Encoding:% s \ r \ n")% ((UserAgent.GetBrowser () == INTERNET_EXPLORER && UserAgent.GetVersion ()> = 8)? "gzip": "deflate" ); // Bueno eso lo arregla. Sigo buscando una respuesta real, sin embargo, si alguien puede llegar a una. Thomas Bonini

Tu respuesta

2   la respuesta
5

pero hay algunas diferencias sutiles con el encabezado, por lo tanto, si cambias tu codificación de contenido, también deberías cambiar tus parámetros al método de codificación (específicamente , el tamaño de la ventana)!

Ver:http://apcmag.com/improve_your_site_with_http_compression.htm

Probablemente los otros navegadores están ignorando su especificación de codificación de contenido y haciendo algún reconocimiento automático, pero IE8 no es ...

Ver:http://www.zlib.net/manual.html#deflateInit2

Tratar de usar:

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

Y usa "gzip" como la codificación de contenido

¡Wow gracias! Te amo: D Un poco de corrección, sin embargo. Hay 3 (!) Formatos de compresión: zlib, el que estaba usando, que pensé que era "desinflar", desinflar y gzip. Como si no fuera lo suficientemente confuso, los 3 aparentemente se crean usando la biblioteca zlib. Al no especificar los WindowBits (como lo estaba haciendo), se genera el formato zlib, usando un valor negativo (como usted sugirió) produce unDESINFLADO formato (no gzip!). Todavía no estoy seguro de cómo generar el formato gzip (y no me importa, ahora funciona con deflate en todos los navegadores). ¡¡GRACIAS DE NUEVO!! :) Thomas Bonini
+1, buen hallazgo! Supongo que, un error en mod_gzip. j_random_hacker
5

ya que he escrito mi propio algoritmo de desinflado, mi propio servidor HTTP, y para mi consternación, IE8 tampoco reconoció mi contenido desinflado:

HTTP RFC eshttp://www.faqs.org/ftp/rfc/rfc2616.pdf. La página 17 indica que tanto el RFC 1950 como el RFC 1951 se utilizan cuando se realiza un desinflado en los encabezados HTTP. RFC 1950 simplemente define los encabezados y los bytes del tráiler; el algoritmo de desinflado se define en RFC 1951. Cuando programé esto para especificar, IE8 falló.

Cuando ignoré RFC 1950 y solo hice RFC 1951, pasó.

Asumiría, entonces, que IE8 no está siguiendo la página 17 de RFC 2616 correctamente, y todos los demás navegadores son lo suficientemente agradables como para aceptar cualquiera de los dos formatos.

Acabo de encontrar el proxy de almacenamiento en caché web de un cliente que está forzando el desinflado y ¿adivina qué implementación han elegido? El incorrecto, probablemente para soportar IE8. Desafortunadamente, nuestro cliente Java, que utiliza bibliotecas HTTP estándar, espera la implementación de desinflado correcta. Tendré que desactivar el soporte de desinflado en nuestro cliente y forzarlo a usar gzip o nada. Marcus Adams

Preguntas relacionadas