如何使用 Ajax 发出跨域请求?

Posted

技术标签:

【中文标题】如何使用 Ajax 发出跨域请求?【英文标题】:How do I make an Cross Domain Request with Ajax? 【发布时间】:2012-12-22 20:43:11 【问题描述】:

我被要求从 xml 提要中获取一些“数据”并将其添加到我在服务器上托管的页面。我想我会使用 jQuery Ajax api——我得到了这个错误。

XMLHttpRequest cannot load .../3.atom. Origin http://myserver.com is not allowed by Access-Control-Allow-Origin.

我需要向某人请求访问权限吗?有什么我可以添加到我的请求中的吗?我已经阅读了有关 CORS 的内容,在这种情况下我应该使用该服务吗?

这是我目前的代码。

var feedUrl = "http://www.holmanreviews.com/audi-pembroke-pines/3.atom";
var content;

$.ajax(
    type: "GET",
    url: feedUrl,
    dataType: "xml",
    crossDomain: true,
    success: function (xml) 
        $(xml).find('entry').each(function () 
            var $this = $(this);
            var id = $this.attr('id');
            content += id;
        );
    
);

$('#feed').append(content);

我这里也有一个 JS Fiddle。 http://jsfiddle.net/rsturim/6nsyX/

如果你能提供帮助,我会很想知道这方面的背景——非常感谢。

【问题讨论】:

你需要使用 JSONP... JSONP、CORS 或服务器端代理。 您是否在控制远程域?这严重限制了您的选择。 我无法控制远程域 :( 如果您希望使用 jQuery 发出请求并希望获得完整的 IE 支持,我不建议使用 CORS(cors 在 IE7 中无法工作,并且 jQuery 在 IE8 和 9 中不支持 CORS 请求)。服务器端代理将是一种更简单的方法。只需向您的服务器请求数据,然后让您的页面从您的服务器请求数据。 【参考方案1】:

您正确地发出请求,但远程站点需要支持 CORS,而您收到的错误意味着它不支持它。

由于它是 Atom 提要,因此远程站点支持 JSONP 的可能性可能不大,因此您最好的方法是使用代理。您可以使用 Yahoo 的 YQL 来获取 XML 或 JSON,而不是自己滚动。 YQL 确实支持 CORS,所以你可以得到任何一个。

XML:

http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D%22http%3A%2F%2Fwww.holmanreviews.com%2Faudi-pembroke-pines%2F3.atom%22%20and%20itemPath%3D%22feed.entry%22&format=xml

JSON:

http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D%22http%3A%2F%2Fwww.holmanreviews.com%2Faudi-pembroke-pines%2F3.atom%22%20and%20itemPath%3D%22feed.entry%22&format=json

XML 将准确地为您提供直接从该站点获得的内容,但是使用 javascript 解析 XML 并没有太多乐趣,因此我强烈建议使用 JSON。 (您也可以获取 JSONP,但支持 CORS 的 JSON 更好。)

根据您的代码,我很确定您能够从基本 URL 构建这些 URL,所以我将把它留作练习 (-;


哦,如果您确实需要支持早于 10 的 Internet Explorer 版本,或者任何其他不支持 CORS 的浏览器,那么当浏览器支持 CORS 时,这里有一个使用 CORS 的简洁方法,否则使用 JSONP:

dataType: $.support.cors ? "json" : "jsonp"

【讨论】:

【参考方案2】:

您可能需要设置server-side proxy 才能访问此数据。

CORS 不起作用,因为您无法控制服务器。

JSON-P 不起作用,因为服务器似乎不接受“回调”参数。我通过将“?callback = foo”附加到您的请求网址来测试这一点,这并没有改变响应。他们的 API 可能支持回调参数的其他名称,但如果不查看他们的 API 的任何文档就很难知道。

【讨论】:

【参考方案3】:

您必须为此使用 JSONP。打破同源政策是一个很好的技巧。这是非常危险的,所以你必须信任数据的提供者。

在您的请求配置中使用相关的数据类型:

dataType: "xml"

此外,您的提要需要支持 JSONP。这意味着,如果请求 URL 以 callback=? 之类的查询为后缀,则响应必须包装在 Javascript 函数中,并且引号需要转义:

callback("<your-xml>...</your-xml>");

这是 JSONP 的基本思想。如果您想了解为什么必须这样做,请查看 Wikipedia 文章,例如:JSONP

【讨论】:

以上是关于如何使用 Ajax 发出跨域请求?的主要内容,如果未能解决你的问题,请参考以下文章

如何向 Google Site Search XML API 发出跨域浏览器请求?

在 iframe 内容中发出跨域 ajax 请求是不是可行?

怎样避免跨域发出OPTIONS请求?

带有跨域重定向的 Safari xhr (AJAX) 请求失败

如何构建非跨域的 AJAX API?

如何解决 Ajax 跨域请求不到的问题