XMLHttpRequest状态为0(responseText为空)


104

无法使用XMLHttpRequest获取数据(状态0,responseText为空):

xmlhttp = new XMLHttpRequest();
xmlhttp.open(“ GET”,“ http://www.w3schools.com/XML/cd_catalog.xml”,true);
xmlhttp.onreadystatechange = function() 
{
  if(xmlhttp.readyState == 4)
    alert(“ status” + xmlhttp.status);
}
xmlhttp.send();

它警告“状态0”。

与localhost请求的情况相同(cd_catalog.xml保存为本地文件)

xmlhttp.open(“ GET”,“ http://localhost/cd_catalog.xml”,true);

但是使用本地主机IP请求

xmlhttp.open(“ GET”,“ http://127.0.0.1/cd_catalog.xml”,true);

并与本地文件请求

xmlhttp.open(“ GET”,“ cd_catalog.xml”,true);

一切正常(状态200)

什么会导致在线请求出现问题(状态= 0)?

PS:Live HTTP标头显示在所有4种情况下一切正常:

  HTTP / 1.1 200 OK
  内容长度:4742

PS2:VMWare上的Apache本地Web服务器(主机操作系统Win7,来宾操作系统Ubuntu,网络适配器– NAT)。浏览器– Firefox。


1
您的测试页http://127.0.0.1有没有机会?;)
Roatin Marth 2011年


7
你回答了你的问题。XMLHttpRequest不能进行跨域请求。虽然有一些解决方法。以jquery为例。
meze

使用php获取文件。小变通办法:jquery-howto.blogspot.com/2009/04/…– 2011

2
@meze:跨域调用可与jQuery一起使用。但是,由于jQuery是在JavaScript中实现的,因此它不能与普通JavaScript一起使用吗?对我来说完全是无稽之谈。jQuery是否使用某种讨厌的解决方法?
Gruber

Answers:


55

当通过文件方案在浏览器中打开包含脚本的html文件时,状态为0。确保将文件放在您的服务器(apache或tomcat等)中,然后通过浏览器中的http协议将其打开。(即http://localhost/myfile.html)这是解决方案。


1
为什么要对此表示不满?这是真的!来自file:// URL的XHR请求也位于file:// URL上,成功时的状态实际上为== 0(在FF 24.0.5上进行了测试)。
Daniel Roethlisberger 2014年

3
在Safari版本6.1.6上,我也成功获得状态== 0。
2015年

我在firefox 使用“ 加载临时加载项”,状态为= 0(但网络上为状态200)
JobaDiniz

1
仍然有效的答案。对于实际的远程方案(http等),HTTP响应为200;对于本地文件(file://方案),HTTP响应为0 。显然,您需要先通过禁用CORS来允许本地文件加载。
pid

31

问题的原因是您尝试进行跨域调用,但失败

如果您要进行本地主机开发,则可以进行跨域调用-我一直都这样做。

对于Firefox,您必须在配置设置中启用它

signed.applets.codebase_principal_support = true

然后将以下内容添加到您的XHR开放代码中:

  if (isLocalHost()){
    if (typeof(netscape) != 'undefined' && typeof(netscape.security) != 'undefined'){
      netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
    }
  }

对于IE,如果我没记错的话,您要做的就是在“其他→跨域访问数据源”下启用浏览器的“安全性”设置,以使其与ActiveX XHR一起使用。

IE8及更高版本还向本机XmlHttpRequest对象添加了跨域功能,但我还没有使用它们。


8
万一有人需要它,对于Chrome,您需要启动它的新实例(尚未打开任何实例)并使用--allow-file-access-from-files
TheZ 2012年

@TheZ:你是100%吗?听说您只需要通过--allow-file-access-from-filesswitch 运行新的Chrome实例,但不必关闭所有其他正在运行的实例。就像使用Chrome隐身模式一样,您可以在不关闭任何其他正在运行的实例的情况下使用它。
trejder

似乎已删除了对'UniversalBrowserRead'的支持,因此无法解决此问题。
2015年

此外,当您从https页面请求http页面(例如浏览器内扩展名)时,可能会发生这种情况。
sibvic

尽管 html页面和AJAX脚本位于同一域中,我仍遇到此问题。但是奇怪的是,它只影响某些脚本,尤其是访问MongoDB资源的所有脚本。关于这为什么的任何线索?
David Edwards

26

实际上,请确保您的按钮类型为“不提交按钮”,这在我最近遇到的地方造成了状态冲突。


1
之所以存在冲突,是因为提交表单具有一些默认行为,如果您正在处理事件并自己进行ajax调用,则需要阻止这些行为。您可以通过在处理程序中接收事件并致电来阻止默认行为e.preventDefault()
约旦

20

如果服务器使用以下标头响应OPTIONS方法以及GET和POST(无论您使用的是哪种方法):

Access-Control-Allow-Origin: *

可能行得通。似乎在FireFox 3.5和rekonq 0.4.0中。显然,有了该标头和对OPTIONS的初始响应,服务器对浏览器说:“继续进行此跨域请求。”


3
这是正确的答案!有关更多信息,请访问en.wikipedia.org/wiki/Cross-origin_resource_sharing。如果添加此标头,则它不是“可能有效”,而是“将有效”。注意:您需要添加的是HTTP / response /标头-因此您只能在您控制的服务器上执行此操作。永远不可能使用(即按照原始问题)直接获取w3schools.com/XML/cd_catalog.xmlXMLHttpRequest,因为该资源(至少截至2015年4月24日)不包括任何此类CORS标头。
MikeBeaton

13

还考虑请求超时

如果在服务器响应之前经过了太多时间,现代浏览器将返回readyState = 4status = 0


3
@AndreaSavojardo:关于这种行为是否符合标准,您是否有任何参考(例如MDN上的帖子)?
亚历山大·阿巴库莫夫

@AndreaSavojardo我有readyState = 4和status = 0,并且服务器未运行,但是错误的警报很快显示给我....“请求超时”经过了多少时间?

7

添加setRequestHeader("Access-Control-Allow-Origin","*")到您的服务器响应。


3

我曾经遇到过类似的问题。一切正常,“ readystate”为4,但“ status”为0。这是因为我使用的是Apache PHP便携式服务器,而我使用“ XMLHttpRequest”对象的文件是一个html文件。我将文件扩展名更改为php,问题已解决。


3

打开javascript控制台。您会在此处看到错误消息。就我而言,这是CORS。


2

要回答为什么的问题http://127.0.0.1/cd_catalog.xml作品,而 http://localhost/cd_catalog.xml不会:Firefox是治疗和127.0.0.1 localhost作为两个不同的领域。


2

若要查看问题是什么,当您收到神秘错误0时,请转到... |。更多工具| Chrome中的开发者工具(Ctrl + Shift + I)(在显示错误的页面上)

阅读日志中的红色文本以获取真实的错误消息。如果其中太多,请右键单击并清除控制台,然后再次执行上一个请求。

我的第一个问题是,我第一次将“授权”标头传递给浏览器自己的跨域Web服务。

我已经有:

Access-Control-Allow-Origin: *

但不是:

Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization

在我的Web服务的响应标头中。

添加完这些之后,零错误从我自己的Web服务器消失了,以及在没有Web服务器的情况下在本地运行index.html文件时,错误仍然存​​在,但代码笔仍然出现错误。

回到... | 更多工具| 开发人员工具在出现Codepen中的错误的同时,也有明确的解释:Codepen使用https,因此我无法调用http,因为安全性较低。

因此,我需要在https上托管我的Web服务。

知道如何获得真正的错误消息-无价!


我使用了这种方法(chrome中的f12),发现我试图从https转到http,但是却没有提供任何有用的信息而无声地失败了。 错误消息:VM1152:1混合的内容:的页面'https://mysiteoriginsite' 已通过HTTPS加载,但请求了不安全的XMLHttpRequest端点'http://MyDestinationSite/MyService.svc'。该请求已被阻止;内容必须通过HTTPS提供。
GrayDwarf

1

这是另一种情况 status === 0特定于上传:

如果您按照MDN的建议'load'事件处理程序附加到XHR.upload,(向下滚动到“监视进度”的上载部分),则XHR对象将具有并且所有其他属性均为空字符串。如果您附上status=0'load'像在下载内容时那样将处理程序直接到XHR对象,则应该没问题(假设您没有运行localhost)。

但是,如果要在'progress'事件处理程序中获取良好的数据,则需要将处理程序附加到XHR.upload而不是直接附加到XHR对象本身。

到目前为止,我仅在Chrome OSX上进行了测试,所以我不确定这里有多少问题是MDN的文档以及Chrome的实现有多少...


1

亚历克斯·罗宾逊(Alex Robinson)已经(并且首先)给出了此问题的正确答案。但是要详细说明一下...

您必须添加HTTP响应标头:

Access-Control-Allow-Origin: *

如果这样做,结果将不仅是“可能有效”,而且会“有效”。

注意:您需要添加的是HTTP 响应标头-因此您只能在您控制的服务器上执行此操作。永远不可能使用(根据OP的问题)直接从其原始URL 获取http://w3schools.com/XML/cd_catalog.xmlXMLHttpRequest,因为该资源没有(至少,截至2015年4月24日)包括任何此类CORS标头。

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing提供了更多信息。


0

通过检查我的html代码,解决了与此类似的问题。我onclick在表单的提交按钮中有一个处理程序。这样:onclick="sendFalconRequestWithHeaders()"。该方法反过来像您一样调用ajax,并执行我想要的操作。但与预期的不同,我的浏览器未返回任何内容。

某人的辛苦中学习到,我在此处理程序中返回了false,并解决了。让我提到,在到达此职位之前,我花了整整3天半的时间在办公室里编写代码实现CORS filtersjetty config和其他jersey and embedded jetty相关内容-只是为了解决此问题。cross domain ajax requests和标准的东西。javascript中的简单错误使您愚蠢,这太荒谬了。

确实,我已经尝试signed.applets.codebase_principal_support = true并写作过isLocalHost() **if**。可能是我们需要实现此方法,firefox说没有这种方法。现在,我必须清理代码以干净地提交git patch。多亏那个人。


0

浏览器请求“ 127.0.0.1/somefile.html”未更改到达本地网络服务器,而“ localhost / somefile.html”可能以“ 0:0:0:0:0:0:0:1/1 / somefile.html”的形式到达如果支持IPv6。因此,后者可以像从一个域到另一个域一样进行处理。


0

Alex Robinson和bmju提供了有价值的信息,以了解跨域问题。我想补充一点,在进行所需的GET / POST(例如,针对CORS OAuth服务端点)之前,您可能需要在客户端代码中进行显式的OPTIONS调用。您的浏览器/库可能不会自动处理OPTIONS请求。格鲁伯,这是您问题的可能答案之一。


0

我遇到了同样的问题(readyState为4,状态为0),然后我按照本教程中介绍的不同方法进行了处理:https : //spring.io/guides/gs/using-rest-jquery/

他根本不使用XMLHttpRequest,而是使用jquery $ .ajax()方法:

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="hello.js"></script>
</head>

<body>
    <div>
        <p class="greeting-id">The ID is </p>
        <p class="greeting-content">The content is </p>
    </div>
</body>

对于public / hello.js文件(或者您可以将其直接插入相同的HTML代码中):

$(document).ready(function() 
 {
    $.ajax({
        url: "http://rest-service.guides.spring.io/greeting"
   }).then(function(data) {
      $('.greeting-id').append(data.id);
      $('.greeting-content').append(data.content);
   });
 });

2
您确实意识到jQuery 在内部$.ajax()使用XMLHttpRequest了,不是吗?
曼戈


-1

我只是遇到了这个问题,因为我用作0.0.0.0服务器,将其更改为localhost并且可以正常工作。


-4

编辑:由于此答案的知识已过时,请阅读以下Malvolio的评论。

您不能执行跨域XMLHttpRequests。

之所以可以调用,127.0.0.1是因为您的测试页位于127.0.0.1,并且本地测试也可以运行,因为……这是本地测试。

其他两个测试失败,因为JavaScript无法通过XMLHttpRequest与远程服务器通信。

您可以考虑以下两种方法之一:

  • XMLHttp-请求您自己的服务器为您获取远程XML内容(例如php脚本)
  • 如果要保留完整的JavaScript,请尝试使用GoogleAppEngine之类的服务。

希望有帮助


40
这是错误的。您可以执行跨域XMLHttpRequests。
马尔沃里奥(Malvolio)

1
“您不能这样做”中的“您不能这样做”
Gabriel Sprenger

24
-足够公平,但是我不知道评论是否是最好的论坛。跨域XMLHttpRequests确实确实存在一些安全性挑战,但是它们提供了应对这些挑战所必需的所有工具。除此之外,它们还允许网站轻松地向其他网站提供服务,使用CDN传播数据以及更快地响应用户请求。如果您有任何特定问题,可以给我发消息,或者更好的方法是,在SO上在此处发布问题,并引起我的注意。
马尔沃里奥(Malvolio)2012年

2
@GabrielSprenger:跨域XMLHttpRequests不仅是一个主意,而且如今非常普遍,以至于不在现代Web应用程序中(在某种HelloWorlds之外)不使用它们是一件荒谬的事情。您的应用使用的任何外部REST服务都需要跨域 XMLHttpRequest。这就是为什么要添加所有CORS内容的原因。
亚历山大·阿巴库莫夫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.