我正在开发一个页面,该页面通过 jQuery 的 AJAX 支持从 Flickr 和 Panoramio 中提取图像。
Flickr 端工作正常,但是当我尝试从 Panoramio 执行 $.get(url, callback)
时,我在 Chrome 的控制台中看到一个错误:
XMLHttpRequest 无法加载 http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150。 Access-Control-Allow-Origin 不允许 Origin null。
如果我直接从浏览器查询该 URL,它就可以正常工作。发生了什么事,我可以解决这个问题吗?我是否错误地编写了我的查询,或者这是 Panoramio 所做的事情以阻碍我正在尝试做的事情?
Google 没有在 error message 上找到任何有用的匹配项。
编辑
这是一些显示问题的示例代码:
$().ready(function () {
var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';
$.get(url, function (jsonp) {
var processImages = function (data) {
alert('ok');
};
eval(jsonp);
});
});
编辑 2
感谢达林在这方面的帮助。上面的代码是错误的。改用这个:
$().ready(function () {
var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';
$.get(url, function (data) {
// can use 'data' in here...
});
});
document.write
进入的动态生成的 iframe
?
file:///C:/
)。不涉及iframe
。
作为记录,据我所知,您有两个问题:
您没有将“jsonp”类型说明符传递给您的 $.get,因此它使用的是普通的 XMLHttpRequest。但是,您的浏览器支持 CORS(跨域资源共享)以允许跨域 XMLHttpRequest(如果服务器确定)。这就是 Access-Control-Allow-Origin 标头出现的地方。我相信您提到您是从 file:// URL 运行它的。 CORS 标头有两种方式表明跨域 XHR 正常。一种是发送 Access-Control-Allow-Origin: * (如果您是通过 $.get 访问 Flickr,他们一定是这样做的),另一种是回显 Origin 标头的内容。但是,file:// URL 会产生一个空的 Origin,无法通过回显授权。
Darin 建议使用 $.getJSON
以迂回的方式解决了第一个问题。如果它在 URL 中看到子字符串 callback=?
,则将请求类型从默认的“json”更改为“jsonp”会有点神奇。
通过不再尝试从 file://
URL 执行 CORS 请求,解决了第二个问题。
为了向其他人澄清,以下是简单的故障排除说明:
如果您尝试使用 JSONP,请确保满足以下条件之一:您正在使用 $.get 并将 dataType 设置为 jsonp。您正在使用 $.getJSON 并包含 callback=?在网址中。如果您尝试通过 CORS 执行跨域 XMLHttpRequest... 请确保您通过 http:// 进行测试。通过 file:// 运行的脚本对 CORS 的支持有限。确保浏览器确实支持 CORS。 (Opera 和 Internet Explorer 迟到了)
您可能需要在调用的脚本中添加一个 HEADER,这是我在 PHP 中必须做的:
header('Access-Control-Allow-Origin: *');
Cross domain AJAX ou services WEB(法语)中的更多详细信息。
对于一个简单的 HTML 项目:
cd project
python -m SimpleHTTPServer 8000
然后浏览您的文件。
在 Google Chrome v5.0.375.127 上为我工作(我收到警报):
$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
alert(json.photos[1].photoUrl);
});
另外我建议您使用 $.getJSON()
方法,因为以前的方法在 IE8 上不起作用(至少在我的机器上):
$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
alert(json.photos[1].photoUrl);
});
你可以试试online from here。
更新:
现在您已经显示了您的代码,我可以看到它的问题。您同时拥有匿名函数和内联函数,但两者都将被称为 processImages
。这就是 jQuery 的 JSONP 支持的工作原理。请注意我如何定义 callback=?
以便您可以使用匿名函数。您可以阅读更多about it in the documentation。
另一句话是你不应该调用 eval。传递给匿名函数的参数已经被 jQuery 解析为 JSON。
只要请求的服务器支持 JSON 数据格式,就使用 JSONP(JSON Padding)接口。它允许您在没有代理服务器或花哨的标头内容的情况下发出外部域请求。
如果您要进行本地测试或从 file://
之类的地方调用文件,那么您需要禁用浏览器安全性。
在 MAC 上:open -a Google\ Chrome --args --disable-web-security
我们通过 http.conf
文件管理它(编辑然后重新启动 HTTP 服务):
<Directory "/home/the directory_where_your_serverside_pages_is">
Header set Access-Control-Allow-Origin "*"
AllowOverride all
Order allow,deny
Allow from all
</Directory>
在 Header set Access-Control-Allow-Origin "*"
中,您可以输入一个精确的 URL。
就我而言,相同的代码在 Firefox 上运行良好,但在 Google Chrome 上却不行。谷歌浏览器的 JavaScript 控制台说:
XMLHttpRequest cannot load http://www.xyz.com/getZipInfo.php?zip=11234.
Origin http://xyz.com is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"
我不得不删除 Ajax URL 的 www 部分,以便它与原始 URL 正确匹配,然后它工作得很好。
最后请注意,Mozilla documentation explicitly says
如果标头通配符为:Access-Control-Allow-Origin: *,上述示例将失败。由于 Access-Control-Allow-Origin 明确提及 http://foo.example,因此将凭证认知内容返回给调用 Web 内容。
因此,使用“*”不仅仅是一种不好的做法。根本行不通:)
并非所有服务器都支持 jsonp。它要求服务器在其结果中设置回调函数。我使用它从返回纯 json 但不支持 jsonp 的站点获取 json 响应:
function AjaxFeed(){
return $.ajax({
url: 'http://somesite.com/somejsonfile.php',
data: {something: true},
dataType: 'jsonp',
/* Very important */
contentType: 'application/json',
});
}
function GetData() {
AjaxFeed()
/* Everything worked okay. Hooray */
.done(function(data){
return data;
})
/* Okay jQuery is stupid manually fix things */
.fail(function(jqXHR) {
/* Build HTML and update */
var data = jQuery.parseJSON(jqXHR.responseText);
return data;
});
}
我使用 Apache 服务器,所以我使用了 mod_proxy 模块。启用模块:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
然后加:
ProxyPass /your-proxy-url/ http://service-url:serviceport/
最后,将 proxy-url 传递给您的脚本。
对于 PHP - 在 Chrome、safari 和 firefox 上为我工作
header('Access-Control-Allow-Origin: null');
使用 axios 通过 file:// 调用 php 实时服务
header('Access-Control-Allow-Origin: '.( trim($_SERVER['HTTP_REFERER'],'/') ?:'null'),true);
,它也允许从远程服务器到另一个服务器的交叉源,并且本地文件的 (string) null。
我在 Chrome 中也遇到了同样的错误(我没有测试其他浏览器)。这是因为我在 domain.com 而不是 www.domain.com 上导航。有点奇怪,但我可以通过将以下行添加到 .htaccess 来解决问题。它将 domain.com 重定向到 www.domain.com 并解决了问题。我是一个懒惰的网络访问者,所以我几乎从不输入 www,但显然在某些情况下它是必需的。
RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
确保您使用的是最新版本的 JQuery。我们在 JQuery 1.10.2 中遇到了这个错误,并且在使用 JQuery 1.11.1 后该错误得到了解决
伙计们,
我遇到了类似的问题。但是使用 Fiddler,我能够解决这个问题。问题是在 Web API 端的 CORS 实现中配置的客户端 URL 不能有尾部正斜杠。通过 Google Chrome 提交请求并检查 Fiddler 的 Headers 部分的 TextView 选项卡后,错误消息如下所示:
*“指定的策略来源 your_client_url:/' 无效。它不能以正斜杠结尾。”
这真的很古怪,因为它在 Internet Explorer 上运行没有任何问题,但在使用 Google Chrome 进行测试时让我很头疼。
我删除了 CORS 代码中的正斜杠并重新编译了 Web API,现在可以通过 Chrome 和 Internet Explorer 访问 API,没有任何问题。请试一试。
谢谢,安迪
在 by CodeGroover above 发布的解决方案中有一个小问题,如果您更改文件,则必须重新启动服务器才能实际使用更新的文件(至少在我的情况下)。
所以搜索了一下,我发现 this one 使用:
sudo npm -g install simple-http-server # to install
nserver # to use
然后它将在 http://localhost:8000
投放。
不定期副业成功案例分享
callback=?
对我不起作用,但jsonp=?
对我有用。对此有何解释?callback=?
不适合你,因为当前的 jQuery 文档仍然说它应该,但是,如果我正确阅读它们,他们也说anything_else=?
也可以工作。