为什么Internet Explorer不能在失败后的Ajax调用中发送HTTP POST主体?
我们能够可靠地重新创build以下场景:
- 创build一个小的HTML页面,向服务器发出AJAX请求(使用HTTP POST)
- 断开与networking的连接并重新连接
- 监视IE发生故障后的报文
在networking连接失败之后,IE做出下一个AJAX请求,但是只在发送HTTP POST时发送HTTP头 (不是主体)。 这会导致服务器上的各种问题,因为这只是部分请求。 谷歌与Bing这个问题,你会发现很多人抱怨使用AJAX或无法解释的AJAX失败的“随机服务器错误”。
我们知道IE(不像大多数其他浏览器)总是以两个TCP / IP数据包的forms发送HTTP POST。 标题和正文分开发送。 在发生故障后, IE只发送头文件 。
所以我的问题是 – 为什么这样做呢? 这似乎是错误的基于HTTP规范和其他浏览器不这样做。 这只是一个错误? 这确实会在任何严重的基于AJAX的Web应用程序中造成混乱。
参考信息:
有一个类似的问题,由HTTP保持活动超时短于1分钟,这里logging:
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 从不发送有效负载,服务器最终响应超时。 http://img203.imageshack.us/i/retryt.png/
对这个问题似乎没有明确的答案,所以我会提供我的经验数据作为替代,并提供一些方法来解决这个问题。 也许一些MS内幕人士总有一天会对此有所了解。
-
如果在服务器上禁用 HTTP Keep-Alive,则此问题消失。 换句话说,您的HTTP 1.1服务器将响应每个Ajax请求,并在响应中使用
Connection: Close
行。 这使IE很快乐,但导致每个Ajax请求打开一个新的连接。 这可能会对性能产生重大影响,特别是在高延迟networking上。 -
如果Ajax请求快速连续进行,这个问题很容易被触发。 例如,我们每隔100ms发出一次Ajax请求,然后networking状态发生变化,错误很容易重现。 尽pipe大多数应用程序可能不会提出这样的请求,但是也可能会有几个服务器调用发生在彼此之后,这可能会导致此问题。 less说话保持IE快乐。
-
即使没有NTLMauthentication也会发生。
-
如果服务器上的HTTP保持活动超时时间短于默认值(在Windows上默认为60秒),则会发生这种情况。 有关链接中提供的详细信息。
-
Chrome或Firefox不会发生这种情况。 FF发送一个数据包,似乎完全避免了这个问题。
-
它发生在IE 6,7,8。无法与IE 9testing版重现。
当您使用Microsoft Internet Explorer或另一个程序来执行重新POST操作,只有标头数据张贴微软知识库文章似乎解决此问题。
本文提供了一个修补程序。 对于后来的浏览器,如IE8,它表示修补程序已经包含在内, 但需要通过客户端PC上的registry设置启用 。
我有一个类似的问题,其中一些老版本的IE将只发送头,而不是POST的主体。 我的问题竟然与IE和NTLM有关。 既然你没有提到NTLM,这可能没有帮助,但以防万一:
这是很长的一段时间,但IE(甚至Firefox)有时会“记住”它用于HTTP请求的连接。 备注/例子:
-
在Firefox中,如果我更改代理设置并在页面上点击SHIFT-RELOAD,它仍然使用旧代理。 但是,如果我杀了旧的代理(“killall squid”),它开始使用新的代理。
-
当你断开/重新连接,你收到一个新的IP地址或类似的东西? 你可以以某种方式监视旧的IP地址,看IE是否发送数据到该死的地址?
-
我的猜测是IE正在发送数据,只是错误的path。 它可能足够聪明,不会caching“POST”数据包的networking连接,但可能不足以满足POST有效负载的要求。
-
这可能不会影响大多数的AJAX应用程序,因为人们很less断开连接并重新连接到他们的networking?
你使用NTLM身份validation?
使用NTLM身份validation时,IE不发送后期数据。 它发送标题信息,期待未经授权的响应发送授权,并在'重新authentication'发送后。
我今天使用$ .ajax时遇到过类似的问题,可以通过将async设置为false来解决这个问题。
$.ajax({ async: false, url: '[post action url]', data: $form.serialize(), type: 'POST', success: successCallback });