Вот две страницы, test.php и testserver.php.
test.php
<script src="scripts/jq.js" type="text/javascript"></script>
<script>
$(function() {
$.ajax({url:"testserver.php",
success:function() {
alert("Success");
},
error:function() {
alert("Error");
},
dataType:"json",
type:"get"
}
)})
</script>
testserver.php
<?php
$arr = array("element1",
"element2",
array("element31","element32"));
$arr['name'] = "response";
echo json_encode($arr);
?>
Теперь моя проблема: когда оба этих файла находятся на одном сервере (либо на localhost, либо на web-сервере), он работает и вызывается alert("Success")
; Если они находятся на разных серверах, то есть testserver.php на web-сервере, а test.php на localhost, он не работает, и выполняется alert("Error")
. Даже если URL внутри ajax изменен на http://domain.com/path/to/file/testserver.php.
Используйте JSONP.
jQuery:
$.ajax({
url:"testserver.php",
dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
success:function(json){
// do stuff with json (in this case an array)
alert("Success");
},
error:function(){
alert("Error");
}
});
PHP:
<?php
$arr = array("element1","element2",array("element31","element32"));
$arr['name'] = "response";
echo $_GET['callback']."(".json_encode($arr).");";
?>
echo может быть неправильным, я давно не использовал php. В любом случае вам нужно вывести callbackName('jsonString')
, обратите внимание на кавычки. jQuery передаст свое собственное имя обратного вызова, поэтому вам нужно получить его из GET-параметров.
И как написал Стефан Кендалл, $.getJSON() - это короткий метод, но тогда вам нужно добавить 'callback=?'
к url в качестве GET-параметра (да, значение равно ?, jQuery заменяет его своим собственным сгенерированным методом обратного вызова).
JSONP является хорошим вариантом, но есть более простой способ. Вы можете просто установить доступ-контроля-разрешить-происхождение заголовка на ваш сервер. Значение *
примет кросс-доменные AJAX-запросы с любого домена. (https://developer.mozilla.org/en/http_access_control)
Метод для этого варьируется от языка к языку, конечно. Вот это в Rails:
class HelloController < ApplicationController
def say_hello
headers['Access-Control-Allow-Origin'] = "*"
render text: "hello!"
end
end
В этом примере действие say_hello
будет принимать AJAX запросы из любого домена и возвращает ответ "Привет!&и".
Вот пример заголовков, он может вернуть:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: text/html; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "c4ca4238a0b923820dcc509a6f75849b"
X-Runtime: 0.913606
Content-Length: 6
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date: Thu, 01 Mar 2012 20:44:28 GMT
Connection: Keep-Alive
Просто, как это, он имеет некоторые ограничения браузера. См http://caniuse.com/#feat=cors.
Вы можете контролировать это с помощью HTTP-заголовка при добавлении доступ-контроля-разрешить-происхождения. Установка * приму кросс-доменные AJAX-запросы с любого домена.
Используя РНР он's действительно простой, просто добавьте следующую строку в скрипт, который вы хотите иметь доступ к за пределами вашего домена:
header("Access-Control-Allow-Origin: *");
Дон'т забудьте включить модуль mod_headers и в httpd.конф.
Вам нужно взглянуть на Same Origin Policy:
В вычислительной технике политика одинакового происхождения (same origin policy) является важной концепцией безопасности для ряда браузерного программирования языков, таких как JavaScript. Политика политика позволяет скриптам, запущенным на страницах, происходящих с одного и того же сайта. получать доступ друг к другу > к методам и свойствам без особых ограничений, но предотвращает доступ к большинству методов и свойств на страницам на разных сайтах.
Чтобы вы могли получить данные, они должны быть:
одинаковый протокол и хост.
Вам нужно реализовать JSONP, чтобы обойти это.
Пришлось загружать веб-страницы с локального диска "в файл:///с:/тест/htmlpage.HTML-код и" называют "http://localhost/getxml.php" URL-адрес, и сделать это в IE8+ и Firefox12+ браузеры, использовать jQuery версии v1.7.2 lib для минимизации boilerplate кода. После прочтения десятков статей, наконец, понял это. Вот мое резюме.
Вот пример с jQuery AJAX-вызов с некоторых отладки sysouts.
jQuery.support.cors = true;
$.ajax({
url: "http://localhost/getxml.php",
data: { "id":"doc1", "rows":"100" },
type: "GET",
timeout: 30000,
dataType: "text", // "xml", "json"
success: function(data) {
// show text reply as-is (debug)
alert(data);
// show xml field values (debug)
//alert( $(data).find("title").text() );
// loop JSON array (debug)
//var str="";
//$.each(data.items, function(i,item) {
// str += item.title + "\n";
//});
//alert(str);
},
error: function(jqXHR, textStatus, ex) {
alert(textStatus + "," + ex + "," + jqXHR.responseText);
}
});
Это правда, что политику одного источника запрещает JavaScript запросы между доменами, но спецификация CORS позволяет просто доступ к API, который вы искали, и поддерживается текущий пакет основных браузерах.
Как включить кросс-происхождения совместное использование ресурсов для клиента и сервера:
на "Кросс-совместного использования ресурсов (CORS) - это спецификация, которая позволяет по-настоящему открытый доступ через домен-границы. Если вы служите общественного содержания, рекомендуется использовать CORS, чтобы открыть его для всеобщего JavaScript или открыть браузер.&и"
Я использую сервер 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-адрес вашего скрипта.
Это возможно, но вы должны использовать JSONP В, а не в JSON. Стефан's ссылка указывает вам в правильном направлении. На страницу с jQuery Аякс содержит дополнительную информацию о слове JSONP.
Реми острый имеет подробный пример с использованием PHP.
Безопасность браузера предотвращает выполнение ajax-вызова со страницы, расположенной на одном домене, на страницу, расположенную на другом домене; это называется "same-origin policy".
Есть несколько примеров использования JSONP в которых предусмотрена обработка ошибок.
Однако, обратите внимание, что ошибка-событие не срабатывает при использовании JSONP в! См.: http://api.jquery.com/jQuery.ajax/ или https://stackoverflow.com/questions/5247295/jquery-ajax-request-using-jsonp-error
С помощью jQuery документация (ссылка):
Из-за ограничения безопасности браузера, самого "Аякса" и просит подчиняются тем же происхождения политики; запрос не может успешно извлечь данные из другого домена, поддомена или протокола.
Сценарий и JSONP запросы не подлежат и того же происхождения политики ограничений.
Поэтому я буду считать, что вы должны использовать JSONP в запрос. Но не'т пытались это сам.
Я знаю 3 способа решить вашу проблему:
заголовок("по доступ-контроля-позволяет происхождения: *то");`
или просто домен путем добавления кода Беллоу .htaccess файл:
в `<FilesMatch " в.(ТТФ|ОТФ|СРВ|вуф) на"$;> <IfModule mod_headers и.с> SetEnvIf происхождения "http(s)?://(www.)?(google.com/staging.google.com/development.google.com/otherdomain.net/dev02.otherdomain.net)$" AccessControlAllowOrigin=$0 Заголовок добавить доступ-контроля-разрешить-происхождения, %{AccessControlAllowOrigin}е ОКР=AccessControlAllowOrigin
`Для Microsoft Azure, она'ы немного отличаются.
Azure имеет специальные настройки CORS, которые нужно установить. Это'ы по сути то же самое за кулисами, а просто установка коллектора joshuarh упоминает не получится. Документации по Azure для включения доменных крестом можно найти здесь:
https://docs.microsoft.com/en-us/azure/app-service-api/app-service-api-cors-consume-javascript
Я играл вокруг с этим в течение нескольких часов, прежде чем понял, что мой хостинг платформа это специальная установка.
она работает, все, что вам нужно:
РНР:
header('Access-Control-Allow-Origin: http://www.example.com');
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
В JS (jQuery и с AJAX):
var getWBody = $.ajax({ cache: false,
url: URL,
dataType : 'json',
type: 'GET',
xhrFields: { withCredentials: true }
});