Perché Internet Explorer non invia il corpo del messaggio HTTP sulla chiamata Ajax dopo un errore?


114

Siamo in grado di ricreare in modo affidabile il seguente scenario:

  1. Crea una piccola pagina HTML che invia richieste AJAX a un server (utilizzando HTTP POST)
  2. Disconnettiti dalla rete e ricollegati
  3. Monitorare i pacchetti generati da IE dopo l'errore

Dopo una connessione di rete fallita, IE effettua la successiva richiesta AJAX ma invia solo l' intestazione HTTP (non il corpo) quando esegue il post HTTP. Ciò causa tutti i tipi di problemi sul server poiché è solo una richiesta parziale. Cerca questo problema con Bing su Google e troverai molte persone che si lamentano di "errori casuali del server" utilizzando AJAX o errori AJAX inspiegabili.

Sappiamo che IE (a differenza della maggior parte degli altri browser) invia sempre un HTTP POST come DUE pacchetti TCP / IP. L'intestazione e il corpo vengono inviati separatamente. Nel caso subito dopo un errore, IE invia solo l'intestazione . IE non invia mai il payload e il server alla fine risponde con un timeout.

Quindi la mia domanda è: perché si comporta in questo modo? Sembra sbagliato in base alle specifiche HTTP e altri browser non si comportano in questo modo. È semplicemente un bug? Sicuramente questo crea scompiglio in qualsiasi applicazione Web basata su AJAX seria.

Informazioni di riferimento:

Esiste un problema simile, attivato da timeout keep-alive HTTP inferiori a 1 minuto ed è documentato qui:

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


6
Questa è una domanda eccellente e ben definita che merita una risposta. Sfortunatamente, questo è un po 'fuori tema. Non sono sicuro che sarebbe meglio su webmasters.stackexchange.com o superuser.stackexchange.com .
Stephen

3
@ gilly3, penso che qualcosa debba essere sbagliato in me, perché l'ho letto e stavo solo annuendo ...
Ryley

1
@ gilly3: se tradotto in olandese sarebbe corretto, poiché "googelen" è un verbo (anche definito nel dizionario olandese) che significa "cercare nel web" in olandese. Sì, si scrive "googelen" e non "googlen". Strano, lo so. Quindi, potresti semplicemente dire: "Googel dit probleem met Bing." e sarebbe corretto.

11
@ gilly3: Cos'è Bing? Lo cercherò su Google.
Rocket Hazmat

5
"perché si comporta in questo modo?" - accettereste una risposta "Le persone Microsoft, sebbene per la maggior parte brillanti, fanno parte di una cultura della programmazione fondamentalmente diversa da quelli di noi che sono entrati nell'era digitale attraverso DEC, Unix, Apple, Commodore o altri background, e tendono a fare cose che ci fanno rimanere senza fiato per la meraviglia, non per la loro brillantezza, ma per la loro complicata e totale corruzione di cose che sono semplici e dirette per il resto di noi "?
jcomeau_ictx

Risposte:


28

Non sembra esserci una risposta chiara a questa domanda, quindi fornirò i miei dati empirici come sostituto e fornirò alcuni modi per aggirarli. Forse un giorno qualche membro della SM farà luce su questo ...

  1. Se HTTP Keep-Alive è disabilitato sul server, il problema scompare. In altre parole, il tuo server HTTP 1.1 risponderà a ogni richiesta Ajax con una Connection: Closeriga nella risposta. Ciò mantiene IE felice ma fa sì che ogni richiesta Ajax apra una nuova connessione. Ciò può avere un impatto significativo sulle prestazioni, soprattutto su reti ad alta latenza.

  2. Il problema viene attivato facilmente se le richieste Ajax vengono effettuate in rapida successione. Ad esempio, facciamo richieste Ajax ogni 100 ms e poi lo stato della rete cambia, l'errore è facile da riprodurre. Sebbene la maggior parte delle applicazioni probabilmente non effettua tali richieste, potresti avere un paio di chiamate al server che si verificano una dopo l'altra, il che potrebbe portare a questo problema. Meno loquace rende IE felice.

  3. Succede anche senza l'autenticazione NTLM.

  4. Si verifica quando il timeout keep-alive HTTP sul server è più breve del valore predefinito (che è di 60 secondi su Windows). Dettagli forniti nel link in questione.

  5. Non succede con Chrome o Firefox. FF invia un pacchetto quindi sembra evitare del tutto questo problema.

  6. Succede in IE 6, 7, 8. Impossibile riprodurre con IE 9 beta.


4
Esistono altri modi per risolvere questo problema? Qualche correzione di javascript? Ho provato a guardare i vari oggetti XMLHTTP e ancora non hanno risolto il problema.
Berlin Brown

11

L'articolo della KB di Microsoft intitolato Quando si utilizza Microsoft Internet Explorer o un altro programma per eseguire un'operazione di ripetizione POST, solo i dati di intestazione vengono inseriti sembra risolvere questo problema.

L'articolo fornisce un hotfix. Per i browser successivi, come IE8, si dice che l'hotfix è già incluso ma deve essere abilitato tramite le impostazioni del registro sul PC client.


1
Sto riscontrando questo problema con IE10, che l'articolo non menziona.
ClearCloud8

6
L'articolo ora menziona fino a IE11, quindi sembra che non sia mai stato risolto.
teatro

Credo di aver riscontrato questo problema in un sito di produzione - i programmi utente associati al problema corrispondono a IE 8,9,10 e 11.
Millhouse

Qualcuno ha trovato una soluzione alternativa? In particolare mando un 307 e FF, Chrome, Safari ripubblicano i dati al nuovo endpoint - IE no. Non posso chiedere ai miei utenti di hotfix / patch di registro.
Brad Gunn

2

Ho avuto un problema simile in cui alcune versioni precedenti di IE restituivano solo l'header e non il corpo di un POST. Il mio problema si è rivelato correlato a IE e NTLM. Dal momento che non hai menzionato NTLM, questo probabilmente non aiuta, ma per ogni evenienza:

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


Il tuo collegamento è stato utile per risolvere problemi simili in IE 11 e IIS 6.
Harminder

1

Questo è un tentativo lungo, ma IE (e anche Firefox) a volte "ricorda" la connessione che usa per una richiesta HTTP. Note / esempi:

  • In Firefox, se cambio le impostazioni del proxy e premo SHIFT-RELOAD su una pagina, utilizza ancora il vecchio proxy. Tuttavia, se uccido il vecchio proxy ("killall squid"), inizia a utilizzare il nuovo proxy.

  • Quando ti disconnetti / riconnetti, ricevi un nuovo indirizzo IP o qualcosa di simile? Puoi in qualche modo monitorare il vecchio indirizzo IP per vedere se IE sta inviando dati a quell'indirizzo ormai morto?

  • La mia ipotesi è che IE stia inviando i dati, seguendo il percorso sbagliato. Potrebbe essere abbastanza intelligente da non memorizzare nella cache le connessioni di rete per i pacchetti "POST", ma potrebbe non essere abbastanza intelligente da farlo per i payload POST.

  • Questo probabilmente non influisce sulla maggior parte delle app AJAX, poiché le persone raramente si disconnettono e si ricollegano alle loro reti?


2
Penso che il problema sia l'ultimo. Penso che Microsoft utilizzi una politica "succede raramente: non implementare". :)

1
Controllo tutto il traffico HTTP dall'origine alla destinazione. Posso confermare che (a) il mio indirizzo IP non è cambiato e (b) non c'è nessun tentativo di inviare altro. IE apre un nuovo socket e invia una richiesta parziale. Il modo in cui ho letto l'articolo di MS, è che uno dei loro aggiornamenti di sicurezza ha rotto IE. Quindi hanno creato una patch per risolverlo. Ma nel caso volessi che si comportasse nel vecchio modo "rotto", potresti aggiungere questa chiave di registro. Retry_HeaderOnlyPOST_OnConnectionReset. Sto solo cercando di dare un senso alla follia.
Dodgyrabbit

Sul tuo ultimo punto: se hai un'app Ajax che interroga periodicamente, diciamo 10 secondi, scopriamo che se lasciata aperta per alcune ore questo errore si verificherà invariabilmente. Probabilmente connessione Wifi che cade o rete imprecisa, ma la nostra esperienza su questo problema è molto reale.
Dodgyrabbit

1

Stai utilizzando l'autenticazione NTLM?

Quando si utilizza l'autenticazione NTLM, IE non invia dati post. Invia le informazioni di intestazione, si aspetta un'autorizzazione per l'invio di una risposta non autorizzata e dopo la "nuova autenticazione" invia il messaggio.


Non usiamo l'autenticazione NTLM. Succede con richieste anonime.
Dodgyrabbit

0

Oggi ho riscontrato un problema simile durante l'utilizzo di $ .ajax e sono riuscito a risolverlo impostando async su false.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.