2009-07-03 22 views
5

J'ai un problème très étrange .. J'espère vraiment que quelqu'un a une réponse parce que je ne saurais pas où demander d'autre.Internet Explorer 8 + Deflate

J'écris une application cgi en C++ qui est exécutée par Apache et produit du code HTML. Je compresse la sortie HTML moi-même - à partir de mon application C++ - puisque mon hébergeur ne supporte pas mod_deflate pour une raison quelconque.

J'ai testé cela avec Firefox 2, Firefox 3, Opera 9, Opera 10, Google Chrome, Safari, IE6, IE7, IE8, même wget .. Il fonctionne avec RIEN sauf IE8.

IE8 dit simplement "Internet Explorer ne peut pas afficher la page Web", sans aucune information. Je sais que c'est à cause de la compression seulement parce que ça marche si je la désactive.

Savez-vous ce que je fais mal?

J'utilise zlib pour compresser, et le code exact est:

/* 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; 
} 
+0

ok, c'est bizarre. Si j'envoie "gzip" comme encodage de contenu, cela fonctionne sur IE8, mais sur n'importe quel autre navigateur ..: Erreur de codage de contenu La page que vous essayez d'afficher ne peut pas être affichée car elle utilise une forme invalide ou non supportée compression. –

+1

Après plus d'essais .. Si j'envoie le codage de contenu comme gzip (ce n'est pas! C'est deflate) cela fonctionne sur Internet Explorer seulement n'importe quelle version, y compris ie8 alors qu'il ne fonctionne pas sur n'importe quel autre navigateur. Si j'envoie deflate, le bon, il fonctionne sur n'importe quel navigateur y compris IE6 et IE7 mais pas sur IE8 <. < –

+0

On dirait qu'il est temps d'effectuer une détection d'agent utilisateur.Oui, c'est un hack moche, mais dans mon expérience limitée le développement web en est plein. –

Répondre

5

gzip et dégonfler les méthodes ne sont pas les mêmes ... ils sont très proches, mais il y a des différences subtiles avec les En-tête, donc, si vous changez votre encodage de contenu, vous devriez également modifier vos paramètres à la méthode d'encodage (en particulier, la taille de la fenêtre)!

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

probablement les autres navigateurs ignorent vos spécifications de codage de contenu et de faire une reconnaissance automatique, mais IE8 n'est pas ...

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

Essayez d'utiliser:

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

Et utiliser "gzip" comme encodage de contenu

+2

wow, merci! Je t'aime: D Une petite correction, cependant. Il y a 3 (!) Formats de compression: zlib - celui que j'utilisais, que je pensais être "deflate" -, deflate, et gzip. Comme si ce n'était pas assez confus, tous les 3 sont apparemment créés en utilisant la bibliothèque zlib. Ne spécifiant pas les windowBits (comme je le faisais) sort le format zlib, en utilisant une valeur négative (comme vous l'avez suggéré) sort un format ** DEFLATED ** (pas gzip!). Je ne sais pas encore comment sortir le format gzip (et ça m'est égal, maintenant ça fonctionne avec deflate sur tous les navigateurs). MERCI ENCORE!! :) –

+0

+1, belle trouvaille! Envie de ça, un bug dans mod_gzip. –

5

Je voulais clarifier ce que je l'ai découvert à ce sujet, comme je l'ai écrit mon propre algorithme deflate, mon propre serveur HTTP, et à mon grand désarroi IE8 ne reconnaît pas non mon contenu dégonflé:

HTTP RFC est http://www.faqs.org/ftp/rfc/rfc2616.pdf. La page 17 indique que RFC 1950 et RFC 1951 sont utilisés pour effectuer une dégonflement dans les en-têtes HTTP. La RFC 1950 définit simplement les octets d'en-tête et de bas de page; L'algorithme de dégonflement est défini dans RFC 1951. Lorsque j'ai programmé ceci à spec, IE8 a échoué.

Quand j'ai ignoré RFC 1950 et seulement fait RFC 1951, il est passé.

Je suppose, alors, que IE8 ne suit pas correctement la RFC 2616 page 17, et tous les autres navigateurs sont assez gentils pour accepter l'un ou l'autre format.

+0

Je viens de rencontrer le proxy de mise en cache Web d'un client qui force la déflatation, et devinez quelle implémentation il a choisie? Le mauvais, probablement pour soutenir IE8. Malheureusement, notre client Java, utilisant des bibliothèques HTTP standard, attend l'implémentation de dégonflement correcte. Je vais devoir désactiver le support de dégonflement dans notre client, et les forcer à utiliser gzip ou rien. –

Questions connexes