“Access-Control-Allow-Origin 不允许 Origin null”从 file:// URL 运行的应用程序发出的请求出错

发布于 2024-09-17 07:00:47 字数 1821 浏览 6 评论 0原文

我正在开发一个页面,通过 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

笙痞 2024-09-24 07:00:47

根据记录,据我所知,您遇到了两个问题:

  1. 您没有将“jsonp”类型说明符传递给您的 $.get,因此它使用的是普通的 XMLHttpRequest 。但是,您的浏览器支持 CORS(跨源资源共享),如果服务器同意,则允许跨域 XMLHttpRequest。这就是 Access-Control-Allow-Origin 标头出现的地方。

  2. 我相信您提到您是从 file:// URL 运行它。 CORS 标头有两种方式来表明跨域 XHR 正常。一种是发送 Access-Control-Allow-Origin: * (如果您通过 $.get 访问 Flickr,他们一定已经这样做了),而另一种是回显 Origin 标头的内容。但是,file:// URL 会生成一个 null Origin,无法通过 echo-back 进行授权。

第一个问题通过 Darin 建议使用 $.getJSON 的方式以迂回的方式解决了。如果在 URL 中看到子字符串 callback=? ,它会执行一个小魔法,将请求类型从默认的“json”更改为“jsonp”。

通过不再尝试从 file:// URL 执行 CORS 请求,解决了第二个问题。

为了向其他人澄清,以下是简单的故障排除说明:

  1. 如果您尝试使用 JSONP,请确保存在以下情况之一:
    • 您正在使用 $.get 并设置 dataType< /code>jsonp
    • 您使用的是 $.getJSON 并在 URL 中包含 callback=?
  2. 如果您尝试通过 CORS 执行跨域 XMLHttpRequest...
    1. 确保您通过 http:// 进行测试。通过 file:// 运行的脚本对 CORS 的支持有限。
    2. 确保浏览器确实支持 CORS。 (Opera 和 Internet Explorer 迟到了)

For the record, as far as I can tell, you had two problems:

  1. 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 the Access-Control-Allow-Origin header came in.

  2. 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 the Origin header. However, file:// URLs produce a null Origin 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 substring callback=? 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:

  1. If you're trying to use JSONP, make sure one of the following is the case:
    • You're using $.get and set dataType to jsonp.
    • You're using $.getJSON and included callback=? in the URL.
  2. If you're trying to do a cross-domain XMLHttpRequest via CORS...
    1. Make sure you're testing via http://. Scripts running via file:// have limited support for CORS.
    2. Make sure the browser actually supports CORS. (Opera and Internet Explorer are late to the party)
不忘初心 2024-09-24 07:00:47

您可能需要在调用的脚本中添加一个标头,这是我在 PHP 中必须做的事情:

header('Access-Control-Allow-Origin: *');

You need to maybe add a HEADER in your called script, here is what I had to do in PHP:

header('Access-Control-Allow-Origin: *');
过度放纵 2024-09-24 07:00:47

对于简单的 HTML 项目:

Python 2
cd project
python -m SimpleHTTPServer 8000
Python 3
cd project
python -m http.server 8000

然后浏览您的文件。

For a simple HTML project:

Python 2
cd project
python -m SimpleHTTPServer 8000
Python 3
cd project
python -m http.server 8000

Then browse your file.

游魂 2024-09-24 07:00:47

适用于 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);
});

您可以尝试一下 从此处在线


更新:

现在您已经显示了代码,我可以看到它的问题。您同时拥有匿名函数和内联函数,但两者都将被称为 processImages。这就是 jQuery 的 JSONP 支持的工作原理。请注意我如何定义 callback=? 以便您可以使用匿名函数。您可以在文档中阅读更多信息

另一个注释是你不应该调用 eval。传递给匿名函数的参数已经被 jQuery 解析为 JSON。

Works for me on Google Chrome v5.0.375.127 (I get the alert):

$.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);
});

Also I would recommend you using the $.getJSON() method instead as the previous doesn't work on IE8 (at least on my machine):

$.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);
});

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 the callback=? 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.

日记撕了你也走了 2024-09-24 07:00:47

只要请求的服务器支持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.

離人涙 2024-09-24 07:00:47

如果您正在进行本地测试或从 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

白芷 2024-09-24 07:00:47

这是同源策略,您必须使用 JSON-P 接口或在同一个主机。

It's the same origin policy, you have to use a JSON-P interface or a proxy running on the same host.

峩卟喜欢 2024-09-24 07:00:47

我们通过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中设置Access-Control-Allow-Origin "*",可以输入准确的网址。

We managed it via the http.conf file (edited and then restarted the HTTP service):

<Directory "/home/the directory_where_your_serverside_pages_is">
    Header set Access-Control-Allow-Origin "*"
    AllowOverride all
    Order allow,deny
    Allow from all
</Directory>

In the Header set Access-Control-Allow-Origin "*", you can put a precise URL.

梦毁影碎の 2024-09-24 07:00:47

就我而言,相同的代码在 Firefox 上运行良好,但在 Google Chrome 上则不然。 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 正确匹配,然后就可以正常工作了。

In my case, same code worked fine on Firefox, but not on Google Chrome. Google Chrome's JavaScript console said:

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"

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.

澉约 2024-09-24 07:00:47

最后一点,Mozilla 文档明确指出< /a> 那个

如果标头使用通配符,上面的示例将失败:
Access-Control-Allow-Origin: *. 由于 Access-Control-Allow-Origin 明确提及 http:// /foo.example,
凭证识别内容返回到调用网络
内容。

因此,使用“*”不仅仅是一种不好的做法。根本行不通:)

As final note the Mozilla documentation explicitly says that

The above example would fail if the header was wildcarded as:
Access-Control-Allow-Origin: *. Since the Access-Control-Allow-Origin explicitly mentions http://foo.example,
the credential-cognizant content is returned to the invoking web
content.

As consequence is a not simply a bad practice to use '*'. Simply does not work :)

痴意少年 2024-09-24 07:00:47

并非所有服务器都支持 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;
    });
}

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:

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;
    });
}
谜泪 2024-09-24 07:00:47

我使用 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 传递给您的脚本。

I use Apache server, so I've used mod_proxy module. Enable modules:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Then add:

ProxyPass /your-proxy-url/ http://service-url:serviceport/

Finally, pass proxy-url to your script.

可是我不能没有你 2024-09-24 07:00:47

对于 PHP - 这适用于 Chrome、safari 和 firefox

https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null

header('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

header('Access-Control-Allow-Origin: null');

using axios call php live services with file://

陌若浮生 2024-09-24 07:00:47

我在 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]

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.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
山田美奈子 2024-09-24 07:00:47

确保您使用的是最新版本的 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

偏爱自由 2024-09-24 07:00:47

各位,

我遇到了类似的问题。但使用 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

纵山崖 2024-09-24 07:00:47

上面 CodeGroover 发布的解决方案中有一个小问题,如果更改文件,则必须重新启动服务器实际使用更新的文件(至少就我而言)。

所以搜索了一下,我发现 这个 要使用:

sudo npm -g install simple-http-server # to install
nserver # to use

然后它将在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:

sudo npm -g install simple-http-server # to install
nserver # to use

And then it will serve at http://localhost:8000.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文