Почему Internet Explorer не отправляет тело сообщения HTTP после вызова Ajax после сбоя?

Мы можем надежно воссоздать следующий сценарий:

  • Создайте небольшую HTML-страницу, которая делает запросы AJAX на сервере (используя HTTP POST)
  • Отключиться от сети и снова подключиться
  • Отслеживать пакеты, которые IE генерирует после сбоя

После неудачного сетевого подключения IE делает следующий запрос AJAX, но только отправляет HTTP-заголовок (а не тело) при выполнении HTTP-сообщения. Это вызывает всевозможные проблемы на сервере, поскольку это всего лишь частичный запрос. Google эта проблема с Bing, и вы обнаружите, что многие люди жалуются на "случайные ошибки сервера" с использованием AJAX или необъяснимых сбоев AJAX.

Мы знаем, что IE (в отличие от большинства других браузеров) всегда отправляет HTTP POST в виде двух TCP/IP-пакетов. Заголовок и тело отправляются отдельно. В случае непосредственно после сбоя IE отправляет только заголовок.

Итак, мой вопрос: почему он ведет себя так? Похоже, что это неправильно на основе спецификации HTTP, а другие браузеры не ведут себя так. Это просто ошибка? Несомненно, это создает хаос в любом серьезном веб-приложении на основе AJAX.

Справочная информация:

Существует аналогичная проблема, вызванная таймаутами HTTP keep-alive, которые короче 1 минуты и описаны здесь:

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

Ниже перечислены пакеты до и после отказа:

Обратите внимание, как отправляется HTTP-заголовок и полезная нагрузка http://img827.imageshack.us/i/beforee.png/

После сбоя обратите внимание, как отправляется только заголовок. IE никогда не отправляет полезную нагрузку, и сервер в конечном итоге отвечает на Timeout. http://img203.imageshack.us/i/retryt.png/

Ответ 1

Кажется, нет четкого ответа на этот вопрос, поэтому я предоставил свои эмпирические данные в качестве замены и предоставил бы некоторые способы обойти это. Может быть, какой-нибудь MS-инсайдер однажды прольет свет на это...

  • Если HTTP-Keep-Alive на сервере отключен, этот вопрос пропадает. Другими словами, ваш сервер HTTP 1.1 будет отвечать на каждый запрос Ajax с помощью строки Connection: Close в ответе. Это делает IE счастливым, но заставляет каждый запрос Ajax открывать новое соединение. Это может оказать значительное влияние на производительность, особенно в сетях с высокой задержкой.

  • Проблема запускается легко, если запросы Ajax выполняются быстро. Например, мы делаем запросы Ajax каждые 100 мс, а затем меняется состояние сети, ошибка легко воспроизвести. Хотя большинство приложений, вероятно, не делают таких запросов, у вас может быть несколько вызовов сервера, которые происходят сразу после друг друга, что может привести к этой проблеме. Меньше болтовний поддерживает IE счастливым.

  • Это происходит даже без проверки подлинности NTLM.

  • Это случается, когда ваш тайм-аут останова HTTP на сервере короче, чем значение по умолчанию (которое по умолчанию составляет 60 секунд в Windows). Подробности, представленные в соответствующей ссылке.

  • Это не происходит с Chrome или Firefox. FF отправляет один пакет, поэтому, похоже, вообще не следует устранять эту проблему.

  • Это происходит в IE 6, 7, 8. Невозможно воспроизвести с IE 9 beta.

Ответ 2

Статья Microsoft Microsoft KB под названием Когда вы используете Microsoft Internet Explorer или другую программу для выполнения операции повторного POST, публикуются только данные заголовка кажется, исправляет эту проблему.

В статье приведено исправление. Для более поздних браузеров, таких как IE8, говорится, что исправление уже включено , но должно быть включено через настройки реестра на клиентском ПК.

Ответ 3

У меня была аналогичная проблема, когда некоторые более старые версии IE отправляли обратно только заголовок, а не тело POST. Моя проблема оказалась связанной с IE и NTLM. Поскольку вы не упомянули NTLM, это, вероятно, не поможет, но на всякий случай:

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

Ответ 4

Это длинный снимок, но IE (и даже Firefox) иногда "запоминает", соединение, которое оно использует для HTTP-запроса. Примечания/примеры:

  • В Firefox, если я изменю настройки прокси-сервера и нажимаю SHIFT-RELOAD на страницы, он по-прежнему использует старый прокси. Однако, если я убью старую proxy ( "killall squid" ), он начинает использовать новый прокси.

  • При отключении/повторном подключении вы получаете новый IP-адрес или что-нибудь подобное? Можете ли вы как-то контролировать старый IP-адрес, чтобы видеть если IE отправляет данные на этот теперь мертвый адрес?

  • Я предполагаю, что IE отправляет данные, просто неправильно дорожка. Он может быть достаточно умным, чтобы не кэшировать сетевые подключения для Пакеты "POST", но могут быть недостаточно умны, чтобы сделать это для POST Полезная нагрузка.

  • Это, вероятно, не влияет на большинство приложений AJAX, поскольку люди редко отключить и снова подключиться к своим сетям?

Ответ 5

Используете ли вы проверку подлинности NTLM?

При использовании проверки подлинности NTLM IE не отправляет данные post-data. Он отправляет информацию заголовка, ожидает, что авторизация неавторизованного ответа будет отправлена, а после повторной аутентификации отправит сообщение.

Ответ 6

У меня была аналогичная проблема сегодня при использовании $.ajax и удалось исправить ее, установив async в false.

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