Ошибка XmlHttpRequest: Происхождение null не разрешено Access-Control-Allow-Origin

Я разрабатываю страницу, которая извлекает изображения из Flickr и Panoramio через поддержку jQuery AJAX.

Сторона Flickr работает нормально, но когда я пытаюсь $.get(url, callback) из Panoramio, я вижу ошибку в консоли 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. Происхождение null не допускается через Access-Control-Allow-Origin.

Если я запрашиваю этот 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...
  });
});

Ответ 1

Для записи, насколько я могу судить, у вас было две проблемы:

  • Вы не передавали спецификатор типа "jsonp" на ваш $.get, поэтому он использовал обычный XMLHttpRequest. Тем не менее, ваш браузер поддерживает CORS (совместное использование ресурсов Cross-Origin), чтобы разрешить междоменный XMLHttpRequest, если сервер одобрил его. Это где заголовок Access-Control-Allow-Origin.

  • Я полагаю, вы упомянули, что используете его из файла://URL. Для заголовков CORS есть два способа указать, что междоменный XHR в порядке. Один из них - отправить Access-Control-Allow-Origin: * (который, если вы дошли до Flickr через $.get, они, должно быть, делали), в то время как другой должен был отследить содержимое заголовка Origin. Однако file:// URL-адреса создают нуль Origin, который не может быть разрешен посредством эхо-возврата.

Первая была решена окольным путем Даринским предложением использовать $.getJSON. Для изменения типа запроса с его по умолчанию "json" на "jsonp" возникает небольшая магия, если он видит подстроку callback=? в URL-адресе.

Это решило второе, больше не пытаясь выполнить запрос CORS с URL file://.

Чтобы уточнить для других людей, выполните следующие простые инструкции по устранению неполадок:

  • Если вы пытаетесь использовать JSONP, убедитесь, что одно из следующего:
    • Вы используете $.get и установите dataType на jsonp.
    • Вы используете $.getJSON и включаете callback=? в URL.
  • Если вы пытаетесь выполнить междоменный XMLHttpRequest через CORS...
    • Убедитесь, что вы тестируете через http://. Скрипты, запущенные через file://, имеют ограниченную поддержку CORS.
    • Убедитесь, что браузер фактически поддерживает CORS. (Opera и Internet Explorer опаздывают на вечеринку)

Ответ 2

Вам нужно добавить HEADER в ваш вызываемый script, вот что мне нужно было сделать в PHP:

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

Подробнее в Перекрестный домен AJAX ou services WEB (на французском языке).

Ответ 3

Для простого проекта HTML:

cd project
python -m SimpleHTTPServer 8000

Затем просмотрите файл.

Ответ 4

Работает для меня в 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);
});

Вы можете попробовать онлайн здесь.


UPDATE:

Теперь, когда вы показали свой код, я вижу проблему с ним. У вас есть анонимная функция и встроенная функция, но оба они будут называться processImages. Это работает поддержка JQuery JSONP. Обратите внимание, как я определяю callback=?, чтобы вы могли использовать анонимную функцию. Вы можете прочитать об этом в документации.

Еще одно замечание: вы не должны называть eval. Параметр, переданный вашей анонимной функции, уже будет разбираться в JSON с помощью jQuery.

Ответ 5

Пока запрашиваемый сервер поддерживает формат данных JSON, используйте интерфейс JSONP (JSON Padding). Это позволяет вам делать запросы внешнего домена без прокси-серверов или причудливых заголовков.

Ответ 7

Мы справились с ней через файл 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.

Ответ 8

Если вы выполняете локальное тестирование или вызываете файл с чего-то вроде file://, вам необходимо отключить защиту браузера.

В MAC: open -a Google\ Chrome --args --disable-web-security

Ответ 9

В моем случае тот же код отлично работал на Firefox, но не в Google Chrome. Google Chrome консоль Google сказал:

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"

Мне пришлось отказаться от www-части URL-адреса Ajax, чтобы он правильно соответствовал исходному URL-адресу, и тогда он работал нормально.

Ответ 10

Не все серверы поддерживают jsonp. Это требует, чтобы сервер установил в нем функцию обратного вызова. Я использую это, чтобы получить ответы json от сайтов, которые возвращают чистый json, но не поддерживают 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;
    });
}

Ответ 11

Я использую сервер 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/

Наконец, передайте прокси-url на ваш script.

Ответ 12

Как окончательная заметка документация Mozilla явно говорит, что

Приведенный выше пример завершился неудачей, если заголовок был подстановочным знаком: Access-Control-Allow-Origin: *. Так как Access-Control-Allow-Origin явно упоминает http://foo.example, содержимое учетно-зависимой информации возвращается в вызывающий веб-сайт содержание.

Как следствие, это не просто плохая практика использования "*". Просто не работает:)

Ответ 13

Существует небольшая проблема в решении, опубликованном CodeGroover выше, где, если вы меняете файл, вам придется перезапустить сервер, чтобы фактически использовать обновленный файл (по крайней мере, в моем случае).

Поэтому, немного поискав, я нашел это:

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

И тогда он будет работать на http://localhost:8000.

Ответ 14

Я также получил ту же ошибку в 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]

Ответ 15

Убедитесь, что вы используете последнюю версию JQuery. Мы столкнулись с этой ошибкой для JQuery 1.10.2, и ошибка была решена после использования JQuery 1.11.1

Ответ 16

Люди,

У меня возникла аналогичная проблема. Но, используя Fiddler, я смог понять эту проблему. Проблема заключается в том, что URL-адрес клиента, который настроен в реализации CORS на стороне веб-API, не должен иметь завершающего косая черта. После отправки запроса через Google Chrome и ознакомьтесь с вкладкой TextView раздела Заголовки Fiddler, в сообщении об ошибке будет указано примерно следующее:

* "Указанное политическое происхождение your_client_url:/'недействительно. Он не может закончиться косой чертой."

Это настоящая причуда, потому что она работала без каких-либо проблем в Internet Explorer, но при тестировании с использованием Google Chrome у меня была головная боль.

Я удалил косую черту в коде CORS и перекомпилировал веб-API, и теперь API доступен через Chrome и Internet Explorer без каких-либо проблем. Пожалуйста, сделайте это.

Спасибо, Andy

Ответ 17

Я не знаю, почему @echox похоронил свой ответ в комментариях, но
Его ответ - именно то, что мне нужно!

Мне надоело отлаживать наш сайт с помощью Chrome: мне нужно загрузить файлы или взломать локальный сервер для себя.

Некоторые браузеры, такие как chrome, разрешают CORS, если они запускаются с параметром --allow-file-access-from-files - echox 12 июня 12 в 16:20

Никогда бы не увидел это, если бы мне не было скучно пролистывать.
Поскольку задание похожих вопросов просто помечается как дубликат, даже если я хочу получить ответ с программным отключением/обход кода.