Pourquoi Internet Explorer n'envoie-t-il pas le corps de la publication HTTP sur un appel Ajax après un échec?

114

Nous sommes en mesure de recréer de manière fiable le scénario suivant:

  1. Créez une petite page HTML qui envoie des requêtes AJAX à un serveur (en utilisant HTTP POST)
  2. Déconnectez-vous du réseau et reconnectez-vous
  3. Surveiller les paquets générés par IE après l'échec

Après un échec de connexion réseau, IE effectue la prochaine requête AJAX mais envoie uniquement l' en-tête HTTP (pas le corps) lors de la publication HTTP. Cela provoque toutes sortes de problèmes sur le serveur car il ne s'agit que d'une requête partielle. Recherchez ce problème avec Bing et vous trouverez de nombreuses personnes se plaignant des "erreurs de serveur aléatoires" utilisant AJAX ou des échecs AJAX inexpliqués.

Nous savons que IE (contrairement à la plupart des autres navigateurs) envoie toujours un HTTP POST sous forme de DEUX paquets TCP / IP. L'en-tête et le corps sont envoyés séparément. Dans le cas directement après une panne, IE envoie uniquement l'en-tête . IE n'envoie jamais la charge utile et le serveur répond finalement avec un Timeout.

Ma question est donc: pourquoi se comporte-t-il de cette façon? Cela semble faux d'après les spécifications HTTP et les autres navigateurs ne se comportent pas de cette façon. Est-ce simplement un bug? Cela crée sûrement des ravages dans toute application Web sérieuse basée sur AJAX.

Informations de référence:

Il existe un problème similaire, déclenché par des délais d'attente HTTP inférieurs à 1 minute et documenté ici:

http://us.generation-nt.com/xmlhttprequest-post-sometimes-fails-when-server-using-keep-aliv-help-188813541.html

http://support.microsoft.com/default.aspx?kbid=831167

Dodgyrabbit
la source
6
C'est une excellente question bien définie qui mérite une réponse. Malheureusement, c'est un peu hors sujet. Je ne sais pas si ce serait mieux sur webmasters.stackexchange.com ou superuser.stackexchange.com .
Stephen
3
@ gilly3, je pense que quelque chose ne va pas avec moi, parce que j'ai lu cela et je faisais juste un signe de tête ...
Ryley
1
@ gilly3: une fois traduit en néerlandais, ce serait correct, car «googelen» est un verbe (même défini dans le dictionnaire néerlandais) qui signifie «rechercher sur le Web» en néerlandais. Oui, il s'écrit «googelen» et non «googlen». Bizarre, je sais. Donc, vous pourriez simplement dire: "Googel dit probleem a rencontré Bing." et ce serait correct.
11
@ gilly3: Qu'est-ce que Bing? Je vais le chercher sur Google.
Rocket Hazmat le
5
"pourquoi se comporte-t-il de cette façon?" - Accepteriez-vous une réponse "Les gens de Microsoft, bien que pour la plupart brillants, font partie d'une culture de programmation fondamentalement différente de ceux d'entre nous qui sont entrés dans l'ère numérique via DEC, Unix, Apple, Commodore ou d'autres horizons, et ont tendance à faire des choses qui nous émerveillent, non pas de leur éclat, mais de leur surconsommation et de la corruption totale des choses qui sont simples et directes pour le reste d’entre nous »?
jcomeau_ictx

Réponses:

28

Il ne semble pas y avoir de réponse claire à cette question, je vais donc fournir mes données empiriques en guise de substitut et proposer des moyens de la contourner. Peut-être qu'un initié de MS éclairera un jour ce sujet ...

  1. Si HTTP Keep-Alive est désactivé sur le serveur, ce problème disparaît. En d'autres termes, votre serveur HTTP 1.1 répondra à chaque requête Ajax avec une Connection: Closeligne dans la réponse. Cela rend IE heureux mais provoque chaque requête Ajax pour ouvrir une nouvelle connexion. Cela peut avoir un impact significatif sur les performances, en particulier sur les réseaux à latence élevée.

  2. Le problème se déclenche facilement si les requêtes Ajax sont effectuées en succession rapide. Par exemple, nous faisons des requêtes Ajax toutes les 100 ms puis l'état du réseau change, l'erreur est facile à reproduire. Bien que la plupart des applications ne font probablement pas de telles demandes, il se peut que vous ayez quelques appels au serveur juste après l'autre, ce qui pourrait entraîner ce problème. Moins de bavardage rend IE heureux.

  3. Cela se produit même sans authentification NTLM.

  4. Cela se produit lorsque votre délai d'attente HTTP sur le serveur est plus court que la valeur par défaut (qui est par défaut de 60 secondes sous Windows). Détails fournis dans le lien en question.

  5. Cela ne se produit pas avec Chrome ou Firefox. FF envoie un paquet semble donc éviter complètement ce problème.

  6. Cela se produit dans IE 6, 7, 8. Impossible de reproduire avec IE 9 beta.

Dodgyrabbit
la source
4
Existe-t-il d'autres moyens de résoudre ce problème? Un correctif javascript? J'ai essayé de regarder les différents objets XMLHTTP et ils n'ont toujours pas résolu le problème.
Berlin Brown
11

L'article de la base de connaissances de Microsoft intitulé Lorsque vous utilisez Microsoft Internet Explorer ou un autre programme pour effectuer une opération de re-POST, seules les données d'en-tête sont publiées semblent résoudre ce problème.

L'article fournit un correctif. Pour les navigateurs ultérieurs tels que IE8, il indique que le correctif est déjà inclus mais doit être activé via les paramètres de registre sur le PC client.

julien
la source
1
Je rencontre ce problème avec IE10, que l'article ne mentionne pas.
ClearCloud8
6
L'article mentionne maintenant jusqu'à IE11, il semble donc que cela n'a jamais été corrigé.
peater
Je crois que je rencontre ce problème sur un site de production - les agents utilisateurs associés au problème correspondent à IE 8,9,10 et 11.
moulin
Quelqu'un a-t-il trouvé une solution de contournement? Plus précisément, j'envoie un 307 et FF, Chrome, Safari republier les données vers le nouveau point de terminaison - IE ne le fait pas. Je ne peux pas demander à mes utilisateurs de correctif / correctif de registre.
Brad Gunn
2

J'ai eu un problème similaire où certaines anciennes versions d'IE ne renvoyaient que l'en-tête et non le corps d'un POST. Mon problème s'est avéré être lié à IE et NTLM. Puisque vous n'avez pas mentionné NTLM, cela n'aide probablement pas, mais juste au cas où:

http://support.microsoft.com/kb/251404

réassembleur
la source
Votre lien a été utile pour résoudre un problème similaire dans IE 11 et IIS 6.
Harminder
1

Ceci est long, mais IE (et même Firefox) "se souvient" parfois de la connexion qu'il utilise pour une requête HTTP. Notes / exemples:

  • Dans Firefox, si je change les paramètres du proxy et que je clique sur SHIFT-RELOAD sur une page, il utilise toujours l'ancien proxy. Cependant, si je tue l'ancien proxy ("killall squid"), il commence à utiliser le nouveau proxy.

  • Lorsque vous vous déconnectez / vous reconnectez, recevez-vous une nouvelle adresse IP ou quelque chose de similaire? Pouvez-vous en quelque sorte surveiller l'ancienne adresse IP pour voir si IE envoie des données à cette adresse désormais morte?

  • Je suppose que IE envoie les données, juste dans le mauvais chemin. Il peut être assez intelligent pour ne pas mettre en cache les connexions réseau pour les paquets «POST», mais peut ne pas être assez intelligent pour le faire pour les charges utiles POST.

  • Cela n'affecte probablement pas la plupart des applications AJAX, car les gens se déconnectent et se reconnectent rarement à leurs réseaux?


la source
2
Je pense que le problème est le dernier. Je pense que Microsoft utilise une politique "qui arrive rarement: ne pas implémenter". :)
1
Je surveille tout le trafic HTTP de la source à la destination. Je peux confirmer que (a) mon adresse IP n'a pas changé et (b) il n'y a aucune tentative d'envoyer quoi que ce soit d'autre. IE ouvre un nouveau socket et envoie une requête partielle. La façon dont j'ai lu l'article MS, est l'une de leurs mises à jour de sécurité a cassé IE. Ensuite, ils ont créé un correctif pour résoudre ce problème. Mais juste au cas où vous voudriez qu'il se comporte de l'ancienne manière «cassée», vous pouvez ajouter cette clé de registre. Retry_HeaderOnlyPOST_OnConnectionReset. J'essaie juste de donner un sens à la folie.
Dodgyrabbit le
Sur votre dernier point: si vous avez une application Ajax qui interroge périodiquement, disons 10 secondes, nous constatons que si elle est laissée ouverte pendant quelques heures, cette erreur se produira invariablement. Probablement une connexion Wifi qui tombe ou un réseau fragmentaire - mais notre expérience, ce problème est bien réel.
Dodgyrabbit le
1

Utilisez-vous l'authentification NTLM?

Lors de l'utilisation de l'authentification NTLM, IE n'envoie pas de post-données. Il envoie des informations d'en-tête, attend une autorisation d'envoi de réponse non autorisée et, après la «ré-authentification», envoie le message.

Le-meLLeR
la source
Nous n'utilisons pas l'authentification NTLM. Se produit avec des demandes anonymes.
Dodgyrabbit le
0

J'ai eu un problème similaire aujourd'hui lors de l'utilisation de $ .ajax et j'ai pu le résoudre en définissant async sur false.

$.ajax({
  async: false, 
  url: '[post action url]',
  data: $form.serialize(),
  type: 'POST',
  success: successCallback
});

Robbie Kouwenberg
la source