当HTTP请求返回状态码0时意味着什么?

174
当 JavaScript 网络调用(如 fetch 或 XMLHttpRequest)或任何其他类型的 HTTP 网络请求失败并返回 HTTP 状态码 0 时,这意味着什么?
这似乎不是有效的 HTTP 状态码,因为在 HTTP 规范中其他状态码通常有三个数字。
我尝试完全断开网络作为测试。可能与此无关,但结果显示状态码为 17003(如果我没记错),初步搜索表明这意味着“DNS 服务器查找失败”。
相同的代码在某些位置和系统上运行良好,但在某些环境中会以状态码 0 失败,并且没有提供 responseText。
这是向互联网 URL 发送的典型 HTTP POST 请求。它不涉及 file://,在 Firefox 中返回 0 表示成功,这是我理解的。

可能是由于防火墙导致的吗?您的客户端用的是什么操作系统来运行这个应用程序? - shahkalpesh
可能会有用:https://dev59.com/XG865IYBdhLWcg3wat6l#12622082 - shasi kanth
相关帖子 - HTTP状态码0是什么意思 - RBT
我在Firefox中遇到了同样的问题,发现广告拦截插件阻止了所有包含单词“banner”的URL请求。 - Jan
这个回答解决了你的问题吗?HTTP状态码为0有什么含义吗? - Michael Freidgeim
15个回答

250

这里很多答案是错误的。 看起来人们找出了导致其特定情况下状态为0的原因,然后将其概括为答案。

实际上,对于失败的XmlHttpRequest而言,status==0应被视为未定义的错误。

实际W3C规范定义了返回零的条件: https://fetch.spec.whatwg.org/#concept-network-error

从规范可以看出(fetch或XmlHttpRequest),此代码可能是在与服务器联系之前发生的错误的结果。

产生此状态代码的一些常见情况反映在其他答案中,但也可能是这些问题中的任何一个或没有:

  1. 非法的跨源请求(参见CORS
  2. 防火墙阻止或过滤
  3. 请求本身在代码中被取消
  4. 安装的浏览器扩展程序混淆了事情

有帮助的是,浏览器能够为更多的status==0场景提供详细的错误报告。确实,有时status==0会伴随着一个有用的控制台信息,但在其他情况下却没有其他信息。


4
Firefox插件NoScript可以取消对不受信任主机的XHR请求。 - Ivan Solntsev
13
+1,这完全准确,“发生了某种错误”是其实际解释。对于那些想要了解规范中可能原因的综合列表的人,我在https://dev59.com/XG865IYBdhLWcg3wat6l#26451773上发布了一个详细的分析。 - Mark Amery
1
在Mark Amery详细介绍的情况中,给我带来最大麻烦的是cors案例。如果错误导致响应未能通过cors验证,那么您将获得0状态而不是http状态,因为当cors验证失败时,响应是无法访问的。尤其令人沮丧的是,在尝试检测正在维护并响应503的Web API时,如果此API在维护期间不支持cors,则无法检测到503,您只会得到0,这可能是由许多其他问题引起的。 - Frédéric
1
CORS问题:如果您的页面最初通过http加载,请考虑改用http而不是https,反之亦然。换句话说,如果您的页面通过http访问,请不要通过https执行ajax POST,如果您的页面最初通过https访问,则不要通过http执行ajax POST - Victor Ponamarev
1
这应该是被接受的答案。我想指出的一件事是,您可以向XHR对象添加自定义属性。将某些标志设置为false,然后使用onerror、onabort和ontimeout事件处理程序将适当的标志设置为true。在我的onreadystatechange处理程序中,我将自定义属性设置为当前状态。因此,如果发生错误,我就知道出了什么问题以及链接处于什么状态。 - Daniel Rudy
显示剩余5条评论

69

我认为该错误代码表明响应为空(即没有返回头)。这意味着连接已被接受,然后优雅地关闭(TCP FIN)。 有很多原因可能会导致这种情况,但根据您的描述,某种形式的防火墙似乎是最有可能的罪魁祸首。


2
我想你可能是对的。(尽管,正如@sleepycod所指出的,wininet.dll在没有真实的HTTP状态码的情况下应该返回一些状态码。) - mike nelson
1
这不一定是正确的。我也遇到了同样的问题,但在我的情况下,请求从未被发送。原因是Firefox广告拦截器阻止了包含单词“banner”的URL的请求。 - Jan
错误。你会得到一个状态=0的三类错误。它们是中止、超时和错误。前两个是不言自明的。错误表示发生了网络级别的错误,根据经验,通常会在控制台中记录下来。 - Daniel Rudy

36

就其价值而言,根据浏览器的不同,基于jQuery的AJAX调用将以HTTP状态码0调用成功回调函数。我们发现,“0”状态码通常意味着用户在AJAX调用完成之前导航到了其他页面。

虽然技术栈与您使用的不同,但希望对某些人有用。


是的,人们可能经常遇到这个问题,因为这个页面已经有10,000次浏览了。 - mike nelson
还是应该说25,000次浏览? - mike nelson
3
很有价值:这正是我的自动化测试中出现问题的地方。非常感谢! - alexfernandez
点赞并不是因为这是“正确”的答案,而是因为这正是在我个人的情况下所发生的事情。 - Ruan Mendes
1
这确实会发生,但这不是您看到错误代码== 0的唯一原因。您不能假设它只是用户导航而过滤掉此类错误消息。 - wal

16

wininet.dll返回如下列出的标准和非标准状态码。

401 - Unauthorized file
403 - Forbidden file
404 - File Not Found
500 - some inclusion or functions may missed
200 - Completed

12002 - Server timeout
12029,12030, 12031 - dropped connections (either web server or DB server)
12152 - Connection closed by server.
13030 - StatusText properties are unavailable, and a query attempt throws an exception

针对状态码"零",您是尝试在运行在web服务器上的本地网页上进行请求,还是在没有web服务器的情况下进行请求?

XMLHttpRequest status = 0 and XMLHttpRequest statusText = unknown可以帮助您在未在web服务器上运行脚本时进行调试。


1
感谢提供代码。不,这不是本地请求,而是从本地运行的 VBScript 发送到互联网上的 Web 服务器的请求。 - mike nelson

11

HTTP响应码为0表示AJAX请求被取消。

这可能是由于超时、XHR中止或防火墙阻止请求。超时是常见的,它意味着请求未能在指定时间内执行。XHR中止非常简单...您实际上可以在XMLHttpRequest对象上调用.abort()来取消AJAX调用。(如果您不希望AJAX调用返回并尝试引用已被销毁的对象,则对于单页面应用程序,这是一个好的实践。)如标记答案中所述,防火墙也能够取消请求并触发此0响应。

XHR中止:使用jQuery中止Ajax请求

var xhr = $.ajax({
    type: "POST",
    url: "some.php",
    data: "name=John&location=Boston",
    success: function(msg){
       alert( "Data Saved: " + msg );
    }
});

//kill the request
xhr.abort()

需要注意的是,在XHR对象上运行.abort()方法也会触发error回调。如果您正在进行任何解析这些对象的错误处理操作,则会很快注意到,已中止的XHR和超时的XHR是相同的,但是使用jQuery时传递给error回调的textStatus将在中止时为"abort",在超时发生时为"timeout"。如果您使用Zepto(与jQuery非常相似),则在中止时errorType将为"error",在超时发生时为"timeout"。

jQuery: error(jqXHR, textStatus, errorThrown);
Zepto:  error(xhr, errorType, error);

6
解决方法:我们最终采取的措施 我们认为这与防火墙有关,因此我们想出了一个解决方法。如果有人遇到同样的问题,以下是我们所做的:
  1. 我们仍然像以前一样使用HTA将数据写入本地硬盘上的文本文件中。

  2. 当用户单击“将数据发送回服务器”时,HTA会读取数据并编写一个包含该数据作为XML数据岛的HTML页面(实际上使用SCRIPT LANGUAGE=XML脚本块)。

  3. HTA在浏览器中启动HTML页面的链接。

  4. 现在,HTML页面包含将数据发布到服务器的JavaScript(使用Microsoft.XMLHTTP)。

希望这可以帮助有类似需求的任何人。在这种情况下,这是一个用于贸易展览会上笔记本电脑上使用的Flash游戏。由于该贸易展览会在另一个国家举行,我们无法访问笔记本电脑,只能通过电子邮件发送给客户。

你好,我正在调查一个类似的问题,这个问题也发生在客户的生产环境中。你说你遇到的问题是由于防火墙引起的。你是否还记得防火墙引起了什么影响,或者是防火墙做了什么导致了这个问题? - Ibrahim Najjar

5
本页上的此答案所述,状态码为0意味着请求由于某种原因失败了,并且javascript库将失败解释为状态码为0。

你可以执行以下任一操作来测试此问题:

1) 使用此Chrome扩展程序Requestly,将您的URL从https版本重定向到http版本,因为这将导致混合内容安全错误,并最终生成状态码为0。这种方法的优点是您无需更改应用程序,只需使用此扩展程序“重写”您的URL即可。

2) 更改应用程序的代码,使其可以选择将您的端点重定向到http版本而不是https版本(或反之亦然)。如果这样做,请求将以状态码0失败。


1
使用这个 Chrome 扩展程序?在 HTA 应用程序中? - Quentin
4
当然,这是个好观点!但大多数来到这里的人并不是为了HTA应用而来。他们是通过谷歌搜索“javascript http状态码0”或类似的词汇来到这里的,因此我认为这个问题中的HTA部分在整体上是最不重要的,而最终它仍然是相关的。 - Brad Parks

2
在我的情况下,当我忘记在我的域名前面加上WWW时,状态变为0。因为我的所有ajax请求都是硬编码的http:/WWW.mydomain.com,而加载的网页只是http://mydomain.com,这成为了一个安全问题,因为它是不同的域名。最终我在我的.htaccess文件中做了一个重定向,总是在前面加上www。

2

我发现了一个新的、未记录的 status == 0 的原因。以下是我的发现:

XMLHttpRequest.status === 0
XMLHttpRequest.readyState === 0
XMLHttpRequest.responseText === ''
XMLHttpRequest.state() === 'rejected'

这不是跨域、网络或由于代码或用户导航取消的请求所致。开发者控制台或网络日志中没有任何信息。

我在state()上找到的文档很少(Mozilla没有列出,W3C也没有),其中没有提到“rejected”。

事实证明是我的广告拦截器(Firefox上的uBlock Origin)引起的。


1
除了李的回答之外,您可以通过切换到同步请求来获取更多关于真正原因的信息,因为您还将获得异常:
function request(url) {
    var request = new XMLHttpRequest();
    try {
        request.open('GET', url, false);
        request.send(null);
    } catch (e) {
        console.log(url + ': ' + e);
    }
}

例如:

网络错误:发生了一个网络错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接