XMLHttpRequest 无法使用 jQuery 加载 URL

Posted

技术标签:

【中文标题】XMLHttpRequest 无法使用 jQuery 加载 URL【英文标题】:XMLHttpRequest cannot load an URL with jQuery 【发布时间】:2011-04-19 05:50:16 【问题描述】:

我正在尝试从“远程”网站获取一些 json 数据。 我在 99000 端口上运行我的 Web 服务,然后在 99001 端口 (http://localhost:99001/index.html) 上启动我的网站。

我收到以下消息:

    XMLHttpRequest cannot load http://localhost:99000/Services.svc/ReturnPersons. Origin http://localhost:99001 is not allowed by Access-Control-Allow-Origin.

即使我将网页作为 HTML 文件启动,我也会得到:

    XMLHttpRequest cannot load http://localhost:99000/Services.svc/ReturnPersons.Origin null is not allowed by Access-Control-Allow-Origin.

Web 服务返回数据。我尝试捕获这样的数据项:

var url = "http://localhost:99000/Services.svc/ReturnPersons";
$.getJSON(url, function (data) 
success: readData(data)
);
function readData(data) 
    alert(data[0].FirstName);

我正在尝试得到这个结构:

["FirstName":"Foo","LastName":"Bar","Hello":"Foo","LastName":"World"]

你知道我为什么会收到这个错误吗?

【问题讨论】:

【参考方案1】:

你不能做一个 XMLHttpRequest 跨域,唯一的“选择”是一种称为 JSONP 的技术,归结为:

要开始请求:使用远程 url 添加一个新的<script> 标记,然后确保远程 url 返回调用您的回调函数的有效 javascript 文件。一些服务支持这一点(并让您在 GET 参数中命名您的回调)。

另一种简单的方法是在本地服务器上创建一个“代理”,它会获取远程请求,然后将其“转发”回您的 javascript。

编辑/添加:

我看到 jQuery 内置了对 JSONP 的支持,通过检查 URL 是否包含“callback=?” (jQuery 将替换 ? 与实际的回调方法)。但是您仍然需要在远程服务器上对其进行处理以生成有效的响应。

【讨论】:

我通过添加“&callback=?”解决了这个问题到网址。谢谢! 我是否必须在远程服务器上的服务器脚本中指定/实现任何内容? 是的,您的服务器通常会返回 JSON 字符串,例如"foo": "bar" 您需要将 json 字符串包装在处理 json 响应的回调方法(javascript 函数)中。例如myFunction("foo": "bar"); Charles Leaf,其实你错了。还有另一个“选项”,称为 CORS。在此处查看如何启用它:enable-cors.org 你是对的 portforwardpodcast,但是当这个问题最初在 2010 年被问到时,CORS 是一个不太受欢迎的选择(公平地说:一个我当时从未听说过的选择)并且 IE6 支持已被放弃大多数情况下,仍然需要支持不支持 CORS 的 IE7,而 IE8 仅部分支持它。因此,根据您的要求,这是一个非常有效(并且更好)的选择。【参考方案2】:

在新的 jQuery 1.5 中你可以使用:

$.ajax(
    type: "GET",
    url: "http://localhost:99000/Services.svc/ReturnPersons",
    dataType: "jsonp",
    success: readData(data),
    error: function (xhr, ajaxOptions, thrownError) 
      alert(xhr.status);
      alert(thrownError);
    
)

【讨论】:

我,猜你的回复是额外的“:”。你能粘贴整条消息吗?【参考方案3】:

Fiddle with 3 working solutions 在行动。

给定一个外部 JSON:

myurl = 'http://wikidata.org/w/api.php?action=wbgetentities&sites=frwiki&titles=France&languages=zh-hans|zh-hant|fr&props=sitelinks|labels|aliases|descriptions&format=json'

方案一:$.ajax() + jsonp:

$.ajax(
  dataType: "jsonp",
  url: myurl ,
  ).done(function ( data ) 
  // do my stuff
);

方案二:$.ajax()+json+&calback=?:

$.ajax(
  dataType: "json",
  url: myurl + '&callback=?',
  ).done(function ( data ) 
  // do my stuff
);

解决方案 3:$.getJSON()+calback=?:

$.getJSON( myurl + '&callback=?', function(data) 
  // do my stuff
);

文档:http://api.jquery.com/jQuery.ajax/,http://api.jquery.com/jQuery.getJSON/

【讨论】:

JSfiddle 在#wikidata API 更改后修复,jsfiddle 改进完成,修订改进完成! @TuhinPaul:当您使用 https 小提琴时,您不能请求 http wikidata 或其他 http,这将是安全漏洞。您可以使用 http-http、https-https 或 http-https,而不是 https-http。这是一项安全功能,而不是跨域问题。【参考方案4】:

找到了一个我认为没有被提及的可能的解决方法。

下面是对问题的一个很好的描述: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

基本上只要你使用表单/url-encoded/纯文本内容类型就可以了。

$.ajax(
    type: "POST",
    headers: 
        'Accept': 'application/json',
        'Content-Type': 'text/plain'
    ,
    dataType: "json",
    url: "http://localhost/endpoint",
    data: JSON.stringify('DataToPost': 123),
    success: function (data) 
        alert(JSON.stringify(data));
    
);     

我将它与 ASP.NET WebAPI2 一起使用。所以在另一端:

public static void RegisterWebApi(HttpConfiguration config)

    config.MapHttpAttributeRoutes();

    config.Formatters.Clear();
    config.Formatters.Add(new JsonMediaTypeFormatter());

    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));

这种方式在解析纯文本内容类型时使用 Json 格式化程序。

不要忘记在 Web.config 中:

<system.webServer>
<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="GET, POST" />
  </customHeaders>
</httpProtocol>    

希望这会有所帮助。

【讨论】:

【参考方案5】:

我正在使用 WebAPI 3 并且遇到了同样的问题。随着@Rytis 添加了他的解决方案,该问题已得到解决。而且我认为在 WebAPI 3 中,我们不需要定义方法 RegisterWebApi

我的更改仅在 web.config 文件中并且正在运行。

<httpProtocol>
 <customHeaders>
 <add name="Access-Control-Allow-Origin" value="*" />
 <add name="Access-Control-Allow-Methods" value="GET, POST" />
</customHeaders>
</httpProtocol> 

感谢@Rytis 的解决方案!

【讨论】:

以上是关于XMLHttpRequest 无法使用 jQuery 加载 URL的主要内容,如果未能解决你的问题,请参考以下文章

无法通过 xmlhttprequest 加载本地 xml 文件

XMLHttprequest 无法使用 twitch.tv api

无法使用 XMLHttpRequest 绘制音频文件的波形

无法使用 WKWebView 通过 XMLHttpRequest 加载音频文件

为啥在使用 setRequestHeader 制作 xmlhttprequest 时无法设置 cookie 和 set-cookie 标头?

离子 - XMLHttpRequest 无法加载