“Access-Control-Allow-Origin 不允许 Origin null”从 file:// URL 运行的应用程序发出的请求出错
我正在开发一个页面,通过 jQuery 的 AJAX 支持从 Flickr 和 Panoramio 提取图像。
Flickr 端工作正常,但当我尝试从 Panoramio 执行 $.get(url, callback)
时,我在 Chrome 控制台中看到错误:
XMLHttpRequest 无法加载 http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=测试&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150。 Access-Control-Allow-Origin 不允许 Origin null。
如果我直接从浏览器查询该 URL,它就可以正常工作。发生了什么事,我可以解决这个问题吗?我是否错误地编写了查询,或者这是 Panoramio 所做的事情来阻碍我想做的事情吗?
Google 没有在 错误消息。
编辑
以下是一些显示问题的示例代码:
$().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...
});
});
I'm developing a page that pulls images from Flickr and Panoramio via jQuery's AJAX support.
The Flickr side is working fine, but when I try to $.get(url, callback)
from Panoramio, I see an error in Chrome's console:
XMLHttpRequest cannot load 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. Origin null is not allowed by Access-Control-Allow-Origin.
If I query that URL from a browser directly it works fine. What is going on, and can I get around this? Am I composing my query incorrectly, or is this something that Panoramio does to hinder what I'm trying to do?
Google didn't turn up any useful matches on the error message.
EDIT
Here's some sample code that shows the problem:
$().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);
});
});
You can run the example online.
EDIT 2
Thanks to Darin for his help with this. THE ABOVE CODE IS WRONG. Use this instead:
$().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...
});
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
根据记录,据我所知,您遇到了两个问题:
您没有将“jsonp”类型说明符传递给您的
$.get
,因此它使用的是普通的 XMLHttpRequest 。但是,您的浏览器支持 CORS(跨源资源共享),如果服务器同意,则允许跨域 XMLHttpRequest。这就是Access-Control-Allow-Origin
标头出现的地方。我相信您提到您是从 file:// URL 运行它。 CORS 标头有两种方式来表明跨域 XHR 正常。一种是发送
Access-Control-Allow-Origin: *
(如果您通过$.get
访问 Flickr,他们一定已经这样做了),而另一种是回显 Origin 标头的内容。但是,file://
URL 会生成一个 nullOrigin
,无法通过 echo-back 进行授权。第一个问题通过 Darin 建议使用 $.getJSON 的方式以迂回的方式解决了。如果在 URL 中看到子字符串
callback=?
,它会执行一个小魔法,将请求类型从默认的“json”更改为“jsonp”。通过不再尝试从
file://
URL 执行 CORS 请求,解决了第二个问题。为了向其他人澄清,以下是简单的故障排除说明:
$.get
并设置dataType< /code>
到
jsonp
。$.getJSON
并在 URL 中包含callback=?
。http://
进行测试。通过file://
运行的脚本对 CORS 的支持有限。For the record, as far as I can tell, you had two problems:
You weren't passing a "jsonp" type specifier to your
$.get
, so it was using an ordinary XMLHttpRequest. However, your browser supported CORS (Cross-Origin Resource Sharing) to allow cross-domain XMLHttpRequest if the server OKed it. That's where theAccess-Control-Allow-Origin
header came in.I believe you mentioned you were running it from a file:// URL. There are two ways for CORS headers to signal that a cross-domain XHR is OK. One is to send
Access-Control-Allow-Origin: *
(which, if you were reaching Flickr via$.get
, they must have been doing) while the other was to echo back the contents of theOrigin
header. However,file://
URLs produce a nullOrigin
which can't be authorized via echo-back.The first was solved in a roundabout way by Darin's suggestion to use
$.getJSON
. It does a little magic to change the request type from its default of "json" to "jsonp" if it sees the substringcallback=?
in the URL.That solved the second by no longer trying to perform a CORS request from a
file://
URL.To clarify for other people, here are the simple troubleshooting instructions:
$.get
and setdataType
tojsonp
.$.getJSON
and includedcallback=?
in the URL.http://
. Scripts running viafile://
have limited support for CORS.您可能需要在调用的脚本中添加一个标头,这是我在 PHP 中必须做的事情:
You need to maybe add a HEADER in your called script, here is what I had to do in PHP:
对于简单的 HTML 项目:
Python 2
Python 3
然后浏览您的文件。
For a simple HTML project:
Python 2
Python 3
Then browse your file.
适用于 Google Chrome v5.0.375.127(我收到警报):
另外我建议您使用
$.getJSON()
方法,因为前一个方法在 IE8 上不起作用(至少在我的机器上):您可以尝试一下 从此处在线。
更新:
现在您已经显示了代码,我可以看到它的问题。您同时拥有匿名函数和内联函数,但两者都将被称为
processImages
。这就是 jQuery 的 JSONP 支持的工作原理。请注意我如何定义callback=?
以便您可以使用匿名函数。您可以在文档中阅读更多信息。另一个注释是你不应该调用 eval。传递给匿名函数的参数已经被 jQuery 解析为 JSON。
Works for me on Google Chrome v5.0.375.127 (I get the alert):
Also I would recommend you using the
$.getJSON()
method instead as the previous doesn't work on IE8 (at least on my machine):You may try it online from here.
UPDATE:
Now that you have shown your code I can see the problem with it. You are having both an anonymous function and inline function but both will be called
processImages
. That's how jQuery's JSONP support works. Notice how I am defining thecallback=?
so that you can use an anonymous function. You may read more about it in the documentation.Another remark is that you shouldn't call eval. The parameter passed to your anonymous function will already be parsed into JSON by jQuery.
只要请求的服务器支持JSON数据格式,就使用JSONP(JSON Padding)接口。它允许您在没有代理服务器或花哨的标头内容的情况下发出外部域请求。
As long as the requested server supports the JSON data format, use the JSONP (JSON Padding) interface. It allows you to make external domain requests without proxy servers or fancy header stuff.
如果您正在进行本地测试或从
file://
之类的地方调用文件,那么您需要禁用浏览器安全性。在 MAC 上:
open -a Google\ Chrome --args --disable-web-security
If you are doing local testing or calling the file from something like
file://
then you need to disable browser security.On MAC:
open -a Google\ Chrome --args --disable-web-security
这是同源策略,您必须使用 JSON-P 接口或在同一个主机。
It's the same origin policy, you have to use a JSON-P interface or a proxy running on the same host.
我们通过
http.conf
文件进行管理(编辑后重启HTTP服务):在
Header中设置Access-Control-Allow-Origin "*"
,可以输入准确的网址。We managed it via the
http.conf
file (edited and then restarted the HTTP service):In the
Header set Access-Control-Allow-Origin "*"
, you can put a precise URL.就我而言,相同的代码在 Firefox 上运行良好,但在 Google Chrome 上则不然。 Google Chrome 的 JavaScript 控制台说:
我必须删除 Ajax URL 的 www 部分,才能使其与原始 URL 正确匹配,然后就可以正常工作了。
In my case, same code worked fine on Firefox, but not on Google Chrome. Google Chrome's JavaScript console said:
I had to drop the www part of the Ajax URL for it to match correctly with the origin URL and it worked fine then.
最后一点,Mozilla 文档明确指出< /a> 那个
因此,使用“*”不仅仅是一种不好的做法。根本行不通:)
As final note the Mozilla documentation explicitly says that
As consequence is a not simply a bad practice to use '*'. Simply does not work :)
并非所有服务器都支持 jsonp。它要求服务器在其结果中设置回调函数。我使用它从返回纯 json 但不支持 jsonp 的站点获取 json 响应:
Not all servers support jsonp. It requires the server to set the callback function in it's results. I use this to get json responses from sites that return pure json but don't support jsonp:
我使用 Apache 服务器,所以我使用了 mod_proxy 模块。启用模块:
然后添加:
最后,将 proxy-url 传递给您的脚本。
I use Apache server, so I've used mod_proxy module. Enable modules:
Then add:
Finally, pass proxy-url to your script.
对于 PHP - 这适用于 Chrome、safari 和 firefox
https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null
使用axios调用php live服务与文件://
For PHP - this Work for me on Chrome, safari and firefox
https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null
using axios call php live services with file://
我在 Chrome 中也遇到了同样的错误(我没有测试其他浏览器)。这是因为我在domain.com而不是www.domain.com上导航。有点奇怪,但我可以通过将以下几行添加到 .htaccess 来解决该问题。它将domain.com重定向到www.domain.com,问题就解决了。我是一个懒惰的网络访问者,所以我几乎从不输入 www,但显然在某些情况下这是必需的。
I also got the same error in Chrome (I didn't test other browers). It was due to the fact that I was navigating on domain.com instead of www.domain.com. A bit strange, but I could solve the problem by adding the following lines to .htaccess. It redirects domain.com to www.domain.com and the problem was solved. I am a lazy web visitor so I almost never type the www but apparently in some cases it is required.
确保您使用的是最新版本的 JQuery。我们在 JQuery 1.10.2 中遇到了这个错误,在使用 JQuery 1.11.1 后该错误得到了解决
Make sure you are using the latest version of JQuery. We were facing this error for JQuery 1.10.2 and the error got resolved after using 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,没有任何问题。请尝试一下。
谢谢,
安迪
Folks,
I ran into a similar issue. But using Fiddler, I was able to get at the issue. The problem is that the client URL that is configured in the CORS implementation on the Web API side must not have a trailing forward-slash. After submitting your request via Google Chrome and inspect the TextView tab of the Headers section of Fiddler, the error message states something like this:
*"The specified policy origin your_client_url:/' is invalid. It cannot end with a forward slash."
This is real quirky because it worked without any issues on Internet Explorer, but gave me a headache when testing using Google Chrome.
I removed the forward-slash in the CORS code and recompiled the Web API, and now the API is accessible via Chrome and Internet Explorer without any issues. Please give this a shot.
Thanks,
Andy
上面 CodeGroover 发布的解决方案中有一个小问题,如果更改文件,则必须重新启动服务器实际使用更新的文件(至少就我而言)。
所以搜索了一下,我发现 这个 要使用:
然后它将在
http://localhost:8000
。There is a small problem in the solution posted by CodeGroover above , where if you change a file, you'll have to restart the server to actually use the updated file (at least, in my case).
So searching a bit, I found this one To use:
And then it will serve at
http://localhost:8000
.