Tại sao Internet Explorer không gửi nội dung bài đăng HTTP trên cuộc gọi Ajax sau khi thất bại?


114

Chúng tôi có thể tạo lại kịch bản sau một cách đáng tin cậy:

  1. Tạo một trang HTML nhỏ thực hiện các yêu cầu AJAX đến máy chủ (sử dụng HTTP POST)
  2. Ngắt kết nối khỏi mạng và kết nối lại
  3. Theo dõi các gói mà IE tạo ra sau khi bị lỗi

Sau khi kết nối mạng không thành công, IE thực hiện yêu cầu AJAX tiếp theo nhưng chỉ gửi tiêu đề HTTP (không phải phần thân) khi thực hiện bài đăng HTTP. Điều này gây ra tất cả các loại vấn đề trên máy chủ vì nó chỉ là một yêu cầu một phần. Google vấn đề này với Bing và bạn sẽ thấy nhiều người phàn nàn về "lỗi máy chủ ngẫu nhiên" khi sử dụng AJAX hoặc lỗi AJAX không giải thích được.

Chúng tôi biết rằng IE (không giống như hầu hết các trình duyệt khác) luôn gửi một HTTP POST dưới dạng HAI gói TCP / IP. Tiêu đề và nội dung được gửi riêng biệt. Trong trường hợp trực tiếp sau khi bị lỗi, IE chỉ gửi tiêu đề . IE không bao giờ gửi tải trọng và cuối cùng máy chủ sẽ phản hồi bằng một Thời gian chờ.

Vì vậy, câu hỏi của tôi là - tại sao nó lại hoạt động theo cách này? Có vẻ như sai khi dựa trên thông số HTTP và các trình duyệt khác không hoạt động theo cách này. Nó chỉ đơn giản là một lỗi? Chắc chắn điều này tạo ra sự tàn phá trong bất kỳ ứng dụng Web dựa trên AJAX nghiêm trọng nào.

Tài liệu tham khảo:

Có một sự cố tương tự, được kích hoạt bởi thời gian chờ duy trì HTTP ngắn hơn 1 phút và được ghi lại ở đây:

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
Đây là một câu hỏi tuyệt vời, được xác định rõ ràng và xứng đáng có câu trả lời. Thật không may, điều này là một chút lạc đề. Tôi không chắc liệu nó sẽ tốt hơn trên webmasters.stackexchange.com hay superuser.stackexchange.com .
Stephen

3
@ gilly3, tôi nghĩ rằng một cái gì đó phải xảy ra với tôi, vì tôi đọc đó và chỉ gật đầu cùng ...
Ryley

1
@ gilly3: khi dịch sang tiếng Hà Lan thì điều này sẽ đúng, vì 'googelen' là một động từ (thậm chí được định nghĩa trong từ điển tiếng Hà Lan) có nghĩa là 'tìm kiếm trên web' trong tiếng Hà Lan. Có, nó được đánh vần là 'googelen' chứ không phải 'googlen'. Kỳ lạ, tôi biết. Vì vậy, bạn chỉ có thể nói: 'Googel dit problemem đã gặp Bing.' và nó sẽ đúng.

11
@ gilly3: Bing là gì? Tôi sẽ Google nó.
Rocket Hazmat

5
"tại sao nó lại cư xử theo cách này?" - bạn có chấp nhận cho một câu trả lời "Người của Microsoft, mặc dù về phần lớn là xuất sắc, là một phần của văn hóa lập trình về cơ bản khác với chúng ta, những người bước vào thời đại kỹ thuật số thông qua DEC, Unix, Apple, Commodore, hoặc các nền tảng khác, và có xu hướng làm những điều khiến phần còn lại của chúng ta há hốc mồm kinh ngạc, không phải vì sự xuất chúng của chúng, mà ở sự phức tạp quá mức và sự hư hỏng hoàn toàn của chúng đối với những thứ đơn giản và dễ hiểu đối với phần còn lại của chúng ta "?
jcomeau_ictx

Câu trả lời:


28

Dường như không có câu trả lời rõ ràng cho câu hỏi này, vì vậy tôi sẽ cung cấp dữ liệu thực nghiệm của mình để thay thế và cung cấp một số cách để giải quyết vấn đề đó. Có thể một ngày nào đó người trong MS sẽ làm sáng tỏ điều này ...

  1. Nếu HTTP Keep-Alive bị tắt trên máy chủ, sự cố này sẽ biến mất. Nói cách khác, máy chủ HTTP 1.1 của bạn sẽ phản hồi mọi yêu cầu Ajax bằng một Connection: Closedòng trong phản hồi. Điều này giúp IE hài lòng nhưng khiến mọi yêu cầu Ajax mở một kết nối mới. Điều này có thể có tác động đáng kể đến hiệu suất, đặc biệt là trên các mạng có độ trễ cao.

  2. Sự cố dễ dàng xảy ra nếu các yêu cầu Ajax được thực hiện liên tiếp nhanh chóng. Ví dụ, chúng tôi thực hiện yêu cầu Ajax cứ sau 100ms và sau đó trạng thái mạng thay đổi, lỗi rất dễ tái tạo. Mặc dù hầu hết các ứng dụng có thể không thực hiện các yêu cầu như vậy, bạn cũng có thể có một vài cuộc gọi máy chủ xảy ra ngay sau nhau có thể dẫn đến sự cố này. Ít trò chuyện hơn giúp IE luôn vui vẻ.

  3. Nó xảy ra ngay cả khi không có xác thực NTLM.

  4. Điều này xảy ra khi thời gian chờ duy trì HTTP của bạn trên máy chủ ngắn hơn thời gian mặc định (mặc định là 60 giây trên Windows). Chi tiết được cung cấp trong liên kết được đề cập.

  5. Nó không xảy ra với Chrome hoặc Firefox. FF gửi một gói nên có vẻ như hoàn toàn tránh được vấn đề này.

  6. Nó xảy ra trong IE 6, 7, 8. Không thể tái tạo với IE 9 beta.


4
Có những cách nào khác để khắc phục sự cố này? Bất kỳ bản sửa lỗi javascript nào? Tôi đã thử xem xét các đối tượng XMLHTTP khác nhau và chúng vẫn không khắc phục được sự cố.
Berlin Brown

11

Bài viết microsoft KB có tiêu đề Khi bạn sử dụng Microsoft Internet Explorer hoặc chương trình khác để thực hiện thao tác ĐĂNG lại, chỉ dữ liệu tiêu đề được đăng dường như khắc phục được sự cố này.

Bài báo cung cấp một hotfix. Đối với các trình duyệt mới hơn, chẳng hạn như IE8, nó cho biết hotfix đã được bao gồm nhưng cần được kích hoạt thông qua cài đặt đăng ký trên PC khách.


1
Tôi đang gặp sự cố này với IE10 mà bài viết không đề cập đến.
ClearCloud8

6
Bài viết hiện đề cập đến IE11, vì vậy có vẻ như điều này chưa bao giờ được sửa.
peater

Tôi tin rằng tôi đang gặp vấn đề này trên một trang web sản xuất - các đại lý người dùng liên quan đến việc tương ứng với vấn đề với IE 8,9,10 và 11.
Millhouse

Có ai tìm thấy một giải pháp thay thế? Cụ thể là tôi gửi 307 và FF, Chrome, Safari đăng lại dữ liệu đến điểm cuối mới - IE thì không. Tôi không thể yêu cầu người dùng của mình vá hotfix / đăng ký.
Brad Gunn

2

Tôi đã gặp sự cố tương tự trong đó một số phiên bản IE cũ hơn sẽ chỉ gửi lại Header chứ không phải phần nội dung của POST. Vấn đề của tôi hóa ra liên quan đến IE và NTLM. Vì bạn không đề cập đến NTLM, điều này có thể không hữu ích, nhưng chỉ trong trường hợp:

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


Liên kết của bạn là hữu ích trong việc giải quyết vấn đề tương tự trong IE 11 và IIS 6.
Harminder

1

Đây là một kết quả dài, nhưng IE (và thậm chí cả Firefox) đôi khi "ghi nhớ" kết nối mà nó sử dụng cho một yêu cầu HTTP. Ghi chú / ví dụ:

  • Trong Firefox, nếu tôi thay đổi cài đặt proxy và nhấn SHIFT-RELOAD trên một trang, nó vẫn sử dụng proxy cũ. Tuy nhiên, nếu tôi hủy proxy cũ ("killall ink"), nó sẽ bắt đầu sử dụng proxy mới.

  • Khi ngắt kết nối / kết nối lại, bạn có nhận được địa chỉ IP mới hoặc bất kỳ thứ gì tương tự không? Bằng cách nào đó, bạn có thể theo dõi địa chỉ IP cũ để xem liệu IE có đang gửi dữ liệu đến địa chỉ đã chết đó không?

  • Tôi đoán là IE đang gửi dữ liệu, chỉ là đường dẫn sai. Nó có thể đủ thông minh để không lưu kết nối mạng vào bộ nhớ cache cho các gói "POST", nhưng có thể không đủ thông minh để làm điều đó cho các tải trọng POST.

  • Điều này có lẽ không ảnh hưởng đến hầu hết các ứng dụng AJAX, vì mọi người hiếm khi ngắt kết nối và kết nối lại với mạng của họ?


2
Tôi nghĩ vấn đề là vấn đề cuối cùng. Tôi nghĩ rằng Microsoft sử dụng chính sách "hiếm khi xảy ra: không thực hiện". :)

1
Tôi giám sát tất cả lưu lượng HTTP từ nguồn đến đích. Tôi có thể xác nhận rằng (a) địa chỉ IP của tôi không thay đổi và (b) không có nỗ lực gửi bất kỳ thứ gì khác. IE mở một ổ cắm mới và gửi một phần yêu cầu. Theo cách tôi đọc bài báo của MS, là một trong những bản cập nhật bảo mật của họ đã phá vỡ IE. Sau đó, họ tạo ra một bản vá để sửa lỗi đó. Nhưng trong trường hợp bạn muốn nó hoạt động theo cách cũ "bị hỏng", bạn có thể thêm khóa đăng ký này. Thử lại_HeaderOnlyPOST_OnConnectionReset. Chỉ cố gắng hiểu được sự điên rồ.
Dodgyrabbit

Về điểm cuối cùng của bạn: nếu bạn có một ứng dụng Ajax thăm dò ý kiến ​​định kỳ, chẳng hạn 10 giây, chúng tôi thấy rằng nếu bạn để mở trong vài giờ, lỗi này sẽ luôn xảy ra. Có thể là kết nối Wifi rớt mạng hoặc mạng sơ sài - nhưng trải nghiệm của chúng tôi thì vấn đề này rất thực tế.
Dodgyrabbit

1

Bạn có đang sử dụng xác thực NTLM không?

Khi sử dụng xác thực NTLM, IE không gửi dữ liệu hậu kỳ. Nó gửi thông tin tiêu đề, mong đợi một ủy quyền gửi phản hồi trái phép và sau khi 'xác thực lại' sẽ gửi bài đăng.


Chúng tôi không sử dụng xác thực NTLM. Xảy ra với yêu cầu ẩn danh.
Dodgyrabbit

0

Tôi đã gặp sự cố tương tự hôm nay khi sử dụng $ .ajax và có thể khắc phục sự cố này bằng cách đặt không đồng bộ thành sai.

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.