我们能够可靠地重新创建以下场景:
创建一个小的 HTML 页面,向服务器发出 AJAX 请求(使用 HTTP POST) 断开网络并重新连接 监控 IE 失败后生成的数据包
网络连接失败后,IE 会发出下一个 AJAX 请求,但在进行 HTTP 发布时只发送 HTTP 标头(而不是正文)。这会导致服务器上出现各种问题,因为它只是部分请求。用 Bing 搜索这个问题,你会发现很多人抱怨使用 AJAX 的“随机服务器错误”或无法解释的 AJAX 故障。
我们知道 IE(与大多数其他浏览器不同)总是将 HTTP POST 作为两个 TCP/IP 数据包发送。标头和正文分别发送。在失败后直接的情况下,IE 只发送标头。 IE 从不发送有效负载,服务器最终会以超时响应。
所以我的问题是 - 为什么它会这样?根据 HTTP 规范,这似乎是错误的,其他浏览器的行为方式并非如此。它只是一个错误吗?当然,这会对任何基于 AJAX 的 Web 应用程序造成严重破坏。
参考信息:
有一个类似的问题,由短于 1 分钟的 HTTP 保持活动超时触发,并在此处记录:
http://support.microsoft.com/default.aspx?kbid=831167
这个问题似乎没有明确的答案,所以我将提供我的经验数据作为替代,并提供一些解决方法。也许有一天,一些 MS 内部人员会对此有所了解……
如果在服务器上禁用 HTTP Keep-Alive,此问题就会消失。换句话说,您的 HTTP 1.1 服务器将在响应中使用 Connection: Close 行来响应每个 Ajax 请求。这让 IE 很高兴,但会导致每个 Ajax 请求都打开一个新连接。这可能会对性能产生重大影响,尤其是在高延迟网络上。如果 Ajax 请求快速连续发出,则很容易触发该问题。例如,我们每 100ms 发出一次 Ajax 请求,然后网络状态发生变化,错误很容易重现。尽管大多数应用程序可能不会发出此类请求,但您很可能会同时发生几个服务器调用,这可能会导致此问题。少说话让 IE 开心。即使没有 NTLM 身份验证也会发生这种情况。当服务器上的 HTTP 保持活动超时时间短于默认值(在 Windows 上默认为 60 秒)时,就会发生这种情况。相关链接中提供了详细信息。 Chrome 或 Firefox 不会发生这种情况。 FF 发送一个数据包,因此似乎完全避免了这个问题。它发生在 IE 6、7、8 中。无法使用 IE 9 beta 重现。
标题为When you use Microsoft Internet Explorer or another program to perform a re-POST operation, only the header data is posted 的微软知识库文章似乎解决了这个问题。
本文提供了一个修补程序。对于后来的浏览器,例如 IE8,它表示该修补程序已包含在内,但需要通过客户端 PC 上的注册表设置启用。
我有一个类似的问题,一些旧版本的 IE 只会发回 Header 而不是 POST 的正文。我的问题原来与 IE 和 NTLM 有关。由于您没有提到 NTLM,这可能无济于事,但以防万一:
http://support.microsoft.com/kb/251404
这是一个远景,但 IE(甚至 Firefox)有时会“记住”它用于 HTTP 请求的连接。注释/示例:
在 Firefox 中,如果我更改代理设置并在页面上点击 SHIFT-RELOAD,它仍然使用旧代理。但是,如果我杀死旧代理(“killall squid”),它将开始使用新代理。
当您断开/重新连接时,您是否收到新的 IP 地址或类似的东西?您能否以某种方式监视旧 IP 地址以查看 IE 是否正在向那个现已失效的地址发送数据?
我的猜测是 IE 正在发送数据,只是走错了路。不为“POST”数据包缓存网络连接可能足够聪明,但对于 POST 有效负载可能不够聪明。
这可能不会影响大多数 AJAX 应用程序,因为人们很少断开连接并重新连接到他们的网络?
您是否使用 NTLM 身份验证?
使用 NTLM 身份验证时,IE 不发送后数据。它发送标头信息,期望未经授权的响应发送授权,并在“重新验证”后发送帖子。
我今天在使用 $.ajax 时遇到了类似的问题,并且能够通过将 async 设置为 false 来解决它。
$.ajax({ async: false, url: '[post action url]', data: $form.serialize(), type: 'POST', success: successCallback });
不定期副业成功案例分享