Ошибка XmlHttpRequest: нулевой источник не разрешен Access-Control-Allow-Origin
Я разрабатываю страницу, которая извлекает изображения из Flickr и Panoramio через поддержку jJuery 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. Нулевой источник не разрешен 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...
});
});
16 ответов
Для протокола, насколько я могу судить, у вас было две проблемы:
Вы не передавали спецификатор типа "jsonp"
$.get
так что он использовал обычный XMLHttpRequest. Тем не менее, ваш браузер поддерживает CORS (Cross-Origin Resource Sharing), чтобы разрешить междоменный XMLHttpRequest, если сервер его подтвердил. Вот гдеAccess-Control-Allow-Origin
пришел заголовокЯ полагаю, вы упомянули, что запускаете его из файла:// URL. Есть два способа для заголовков CORS сигнализировать, что междоменный XHR в порядке. Один, чтобы отправить
Access-Control-Allow-Origin: *
(что, если вы достигли Flickr через$.get
, они, должно быть, делали), в то время как другой должен был повторить содержаниеOrigin
заголовок. Тем не мение,file://
URL выдают нольOrigin
который не может быть авторизован через echo-back.
Первый был решен окольным путем предложением Дарина использовать $.getJSON
, Это делает немного волшебства, чтобы изменить тип запроса со своего значения по умолчанию "json" на "jsonp", если он видит подстроку callback=?
в URL.
Это решило второе, больше не пытаясь выполнить запрос CORS от file://
URL.
Чтобы уточнить для других людей, вот простые инструкции по устранению неполадок:
- Если вы пытаетесь использовать JSONP, убедитесь, что имеет место одно из следующих действий:
- Вы используете
$.get
и установитьdataType
вjsonp
, - Вы используете
$.getJSON
и включеныcallback=?
в URL.
- Вы используете
- Если вы пытаетесь сделать междоменный XMLHttpRequest через CORS...
- Убедитесь, что вы тестируете через
http://
, Скрипты, работающие черезfile://
ограниченная поддержка CORS. - Убедитесь, что браузер действительно поддерживает CORS. (Opera и Internet Explorer опаздывают на вечеринку)
- Убедитесь, что вы тестируете через
Возможно, вам нужно добавить HEADER в ваш вызываемый скрипт, вот что я должен был сделать в PHP:
header('Access-Control-Allow-Origin: *');
Более подробная информация в кросс-домене 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);
});
Вы можете попробовать это онлайн здесь.
ОБНОВИТЬ:
Теперь, когда вы показали свой код, я вижу проблему с ним. У вас есть как анонимная, так и встроенная функция, но обе они будут вызваны processImages
, Вот как работает поддержка JSONP в jQuery. Обратите внимание, как я определяю callback=?
так что вы можете использовать анонимную функцию. Вы можете прочитать больше об этом в документации.
Еще одно замечание, что вы не должны звонить Eval. Параметр, переданный вашей анонимной функции, будет уже проанализирован в JSON jQuery.
Пока запрашиваемый сервер поддерживает формат данных JSON, используйте интерфейс JSONP (JSON Padding). Это позволяет вам делать внешние запросы домена без прокси-серверов или причудливых заголовков.
Если вы делаете локальное тестирование или вызываете файл из чего-то вроде file://
тогда вам нужно отключить безопасность браузера.
На MAC:open -a Google\ Chrome --args --disable-web-security
Это та же политика происхождения, вы должны использовать интерфейс JSON-P или прокси, работающий на том же хосте.
Нам удалось через 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 в Google Chrome сказала:
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-адресу, и тогда он работал нормально.
В качестве заключительного замечания в документации Mozilla прямо сказано, что
Вышеприведенный пример потерпит неудачу, если заголовок будет подстановочным символом: Access-Control-Allow-Origin: *. Поскольку Access-Control-Allow-Origin явно упоминает http://foo.example/, контент с удостоверением личности возвращается в вызывающий веб-контент.
Как следствие, это не просто плохая практика использовать "*". Просто не работает:)
Не все серверы поддерживают 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;
});
}
Я использую сервер 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
https://w3c.github.io/webappsec-cors-for-developers/
header('Access-Control-Allow-Origin: null');
используя axios, вызывайте php live services с file://
Я также получил ту же ошибку в 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
Folks,
Я столкнулся с аналогичной проблемой. Но с помощью Fiddler я смог разобраться в проблеме. Проблема заключается в том, что URL-адрес клиента, настроенный в реализации CORS на стороне веб-API, не должен иметь косую черту в конце. После отправки запроса через Google Chrome и проверки вкладки TextView в разделе " Заголовки " Fiddler в сообщении об ошибке говорится что-то вроде этого:
* "Указанный источник политики your_client_url:/'недопустим. Он не может заканчиваться косой чертой."
Это очень странно, потому что он работал без проблем в Internet Explorer, но доставлял мне головную боль при тестировании с использованием Google Chrome.
Я удалил косую черту в коде CORS и перекомпилировал Web API, и теперь API доступен через Chrome и Internet Explorer без каких-либо проблем. Пожалуйста, дайте этому шанс.
Спасибо энди
В решении, опубликованном CodeGroover выше, есть небольшая проблема, когда при изменении файла вам придется перезапустить сервер, чтобы фактически использовать обновленный файл (по крайней мере, в моем случае).
В поисках немного, я нашел этот, чтобы использовать:
sudo npm -g install simple-http-server # to install
nserver # to use
И тогда он будет служить в http://localhost:8000
,