【问题标题】:jQuery ajax crashes chrome on HTTP 206 (Partial content)jQuery ajax 在 HTTP 206 上使 chrome 崩溃(部分内容)
【发布时间】:2013-03-28 16:15:16
【问题描述】:

这件事已经困扰我一段时间了,到目前为止我在网络上找不到原因/解决方案。这是设置:

我有一个在浏览器上运行的胖 JS 客户端,向内部系统发起搜索请求。这些请求只是 GET 的,没什么特别的。它们返回一个 URL,一旦搜索结果可用,就会将其放入其中。

然后我轮询给定的 URL 以获取结果(不时地,比如每 5 分钟一次)并处理要呈现给用户的数据。该 URL 指向一个压缩后的结果文件,它只是一个纯文本 (ASCII)。

现在...搜索结果通常在几百行文本内,但偶尔会有数十万行文本,有时是 7-10MB 的文本(解压缩后)。这就是浏览器显示悲伤标签页的地方。

(无需指出这种方法的安全问题,它们数量众多且非常有效)。

没什么特别的 - 只是调用一个

$.ajax({
    url: '/cgi-bin/ajax_gz.cgi',
    type: 'POST',
    data: 'curl -k "' + self.url_res + '"',
    dataType: 'html',
    success: function (_data, _status, _xhr) {
        self.update_result(_data, _status, _xhr);
    },
    error: function (_xhr, _status, _error) {
        self.set_status(Status.ACK);
    },
    timeout: 5 * ONE_MINUTE
});

ajax_gz.cgi 只不过是一个简单的哑代理(允许我的 JS 通过中继curl 请求从不同域中提取数据):

#!/bin/bash
echo "Content-type: text/html"
echo "Content-encoding: gzip"
echo ""
/bin/bash

返回的确实是压缩后的 HTML,所以我为此设置了标题。我想我可以更新 ajax() 配置中的标头,但这似乎是一种更简单的方法。

successerror 函数永远不会被调用,超时(5 分钟)也不是问题 - 全部在 LAN 上,整个传输不到半分钟。

我可以毫无问题地在选项卡中打开该 URL,它会显示解压缩的计划 ASCII 文本。但是当使用 jQuery 的 ajax() 检索数据时,我面临一个悲伤的标签页(几乎每次,但仅针对“部分内容”HTTP 206 响应)。

我错过了什么?尝试在 JS 调试器中“单步执行”并没有多大帮助,因为我得到的只是一个突然的悲伤标签,然后调试会话被终止。

更新: 单步执行 jQuery 代码并停在 readyState===4 的函数处,我能够捕捉到响应。它是带有全文的HTTP 200(从开始的<html> 标记一直到结束的标记,在单个<pre> 标记之间有108K 行)。 一旦我得到响应并尝试“扩展”this 值,我就会得到一个悲伤的标签页

【问题讨论】:

  • Chrome以外的其他浏览器运行正常吗?
  • 出于兴趣,您是否尝试过使用最新版本的 jQuery?使用 .done()、.fail() 和 .complete() 而不是 .success() 和 .error()。你也可以在尝试跨域之前在你的开发中模拟它吗?
  • 一旦你在 readyState == 4 语句处停下来,你是否能够单步执行直到崩溃?你能够执行的最后一行是什么?
  • @jsha - 只需在 Chrome 选项卡中下载目标 .gz 文件就会导致浏览器崩溃
  • @apsillers - 我没有在 IE 或 FF 中尝试,但 Safari 崩溃了

标签: jquery ajax http google-chrome crash


【解决方案1】:

我认为您遇到了 Chrome 内存限制。编码为this chrome 的 AJAX 调用可能有 3000 个字符的限制。

正如您所注意到的,开发人员工具显示了这一切,但是当读取它以返回给 jQuery 时,它达到了某种形式的上限。您可以尝试将您的响应限制在该限制以下,看看它是否有效?或许换个浏览器试试?

如果这是问题所在,您可以尝试分部分返回结果。退回的一些零件可能会绕过限制。

【讨论】:

  • 该代码肯定已解析(成功)超过 3K 个字符。我已经看到它可以处理多达 3M 的字符。我不控制服务器端,所以改变它返回的内容对我来说是不可能的。
【解决方案2】:

由于您的 bash 代理(哎呀!)不执行任何 gzip 压缩,并且 curl 通常会解压缩它使用 Content-Encoding: gzip 接收到的任何内容,我假设来自您的内部服务器的响应是 gzip 后返回的,但没有存在 Content-Encoding 标头。

听起来您的 curl 脚本正在从您的内部服务器获取 206,对吗?这有点奇怪,因为服务器应该只返回 206 以响应 Range 标头。但是,假设这是给定的,您将获得 gzip 压缩内容的部分响应,并将其作为 200 传递给 Chrome。当然,这不会使 Chrome 崩溃,但其中可能存在错误。

也许尝试解压缩:

#!/bin/bash
echo "Content-type: text/html"
echo ""
curl -k "`cat`" | gunzip

您还想更改您的 Ajax 数据源:

data: self.url_res,

如果失败,请尝试使用 -i 从 curl 捕获完整的标头以进行进一步调试。

【讨论】:

  • 不错的猜测,但并不完全正确。我正在使用该脚本的特殊 gzip 友好版本,它确实放置了正确的 Content-type 标头。 curl不会自动解压缩返回的数据。
猜你喜欢
  • 2016-09-17
  • 2013-03-11
  • 2021-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-19
相关资源
最近更新 更多