AJAX междоменный вызов
Я знаю о междоменной политике AJAX. Поэтому я не могу просто позвонить " http://www.google.com/" через HTTP-запрос ajax и отобразить результаты где-нибудь на моем сайте.
Я пробовал это с dataType "jsonp", который на самом деле будет работать, но я получаю синтаксическую ошибку (очевидно, потому что полученные данные не отформатированы в JSON)
Есть ли другая возможность получать / отображать данные из чужого домена? iFrames следуют той же политике?
11 ответов
Единственный (простой) способ получения междоменных данных с использованием AJAX - это использование языка на стороне сервера в качестве прокси-сервера, как заметил Энди Е. Вот небольшой пример того, как реализовать это с помощью jQuery:
JQuery часть:
$.ajax({
url: 'proxy.php',
type: 'POST',
data: {
address: 'http://www.google.com'
},
success: function(response) {
// response now contains full HTML of google.com
}
});
И PHP (proxy.php):
echo file_get_contents($_POST['address']);
Просто как тот. Просто знайте, что вы можете или не можете делать со скребками данных.
Вам нужно будет динамически вставить тег скрипта на страницу, которая ссылается на данные. Используя JSONP, вы можете выполнить некоторую функцию обратного вызова, когда скрипт загрузится.
Страница википедии на JSONP содержит краткий пример; тег сценария:
<script type="text/javascript" src="http://domain1.com/getjson?jsonp=parseResponse">
</script>
вернет JSON-данные, завернутые в вызов parseResponse
:
parseResponse({"Name": "Cheeso", "Rank": 7})
(в зависимости от конфигурации getjson
скрипт на domain1.com)
Код для динамической вставки тега будет выглядеть примерно так:
var s = document.createElement("script");
s.src = "http://domain1.com/getjson?jsonp=parseResponse";
s.type = "text/javascript";
document.appendChild(s);
Вы можете использовать YQL для выполнения запроса без необходимости размещения собственного прокси. Я сделал простую функцию, чтобы упростить запуск команд:
function RunYQL(command, callback){
callback_name = "__YQL_callback_"+(new Date()).getTime();
window[callback_name] = callback;
a = document.createElement('script');
a.src = "http://query.yahooapis.com/v1/public/yql?q="
+escape(command)+"&format=json&callback="+callback_name;
a.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(a);
}
Если у вас есть jQuery, вы можете использовать вместо него $.getJSON.
Образец может быть таким:
RunYQL('select * from html where url="http://www.google.com/"',
function(data){/* actions */}
);
К сожалению (или к счастью) нет. Междоменная политика существует по определенной причине: если бы ее было легко обойти, то она не была бы очень эффективной в качестве меры безопасности. Кроме JSONP, единственный вариант - прокси страниц, используя ваш собственный сервер.
С iframe они подчиняются той же политике. Конечно, вы можете отображать данные из внешнего домена, вы просто не можете ими манипулировать.
Если вы используете скрипт php для получения ответа от удаленного сервера, добавьте эту строку в начале:
header("Access-Control-Allow-Origin: *");
Я использую этот код для междоменного вызова ajax, я надеюсь, что он поможет больше, чем один здесь. Я использую библиотеку Prototype, и вы можете сделать то же самое с JQuery, Dojo или чем-то еще:
Шаг 1: создайте новый файл js и поместите этот класс внутрь, я назвал его xss_ajax.js
var WSAjax = Class.create ({
initialize: function (_url, _callback){
this.url = _url ;
this.callback = _callback ;
this.connect () ;
},
connect: function (){
var script_id = null;
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', this.url);
script.setAttribute('id', 'xss_ajax_script');
script_id = document.getElementById('xss_ajax_script');
if(script_id){
document.getElementsByTagName('head')[0].removeChild(script_id);
}
// Insert <script> into DOM
document.getElementsByTagName('head')[0].appendChild(script);
},
process: function (data){
this.callback(data) ;
}
}) ;
Этот класс создает динамический элемент сценария, атрибуты src которого предназначены для вашего поставщика данных JSON (фактически JSON-P, поскольку ваш удаленный сервер должен предоставлять данные в этом формате:: call_back_function(//json_data_here)::, поэтому при создании тега сценария JSON будет напрямую вызываться как функция (мы поговорим о передаче имени метода обратного вызова на сервер на шаге 2), основная идея этого заключается в том, что сценарий, подобный элементам img, не касается ограничений SOP.
Шаг 2: на любой html-странице, где вы хотите использовать JSON асинхронно (мы называем это AJAJ ~ Asynchronous JAvascript + JSON:-) вместо AJAX, в котором используется объект XHTTPRequest), выполните следующие действия.
//load Prototype first
//load the file you've created in step1
var xss_crawler = new WSAjax (
"http://your_json_data_provider_url?callback=xss_crawler.process"
, function (_data){
// your json data is _data and do whatever you like with it
}) ;
Вы помните обратный вызов на шаге 1? поэтому мы передаем его на сервер, и он возвращает JSON, встроенный в этот метод, поэтому в нашем случае сервер вернет корректный код javascript xss_crawler.process(//the_json_data), помните, что xss_crawler является экземпляром класса WSAjax. Код сервера зависит от вас (если он ваш), но большинство провайдеров данных Ajax позволяют указывать метод обратного вызова в параметрах, как мы это сделали. В Ruby на рельсах я только что сделал
render :json=>MyModel.all(:limit=>10), :callback => params[:callback],:content_type => "application/json"
и все, теперь вы можете извлекать данные из другого домена из ваших приложений (виджетов, карт и т. д.), только в формате JSON, не забывайте.
Я надеюсь, что это было полезно, спасибо за ваше терпение:-), мир и извините за форматирование кода, это не работает хорошо
После некоторых исследований единственное "решение" этой проблемы - позвонить:
if($.browser.mozilla)
netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
это спросит пользователя, разрешает ли он продолжить работу веб-сайта. После того, как он подтвердил это, все вызовы ajax, независимо от их типа данных, будут выполнены.
Это работает для браузеров Mozilla, в IE < 8 пользователь должен разрешать междоменный вызов аналогичным образом, некоторые версии должны быть настроены в настройках браузера.
Chrome/ Safari: я не нашел флаг настройки для этих браузеров до сих пор.
было бы неплохо использовать JSONP в качестве типа данных, но в моем случае я не знаю, поддерживает ли домен, к которому мне нужен доступ, данные в этом формате.
Еще один способ - использовать HTML5 postMessage, который также работает в междоменных областях, но я не могу позволить себе обречь моих пользователей на браузеры HTML5.
JSONP - лучший вариант, на мой взгляд. Попытайтесь выяснить, почему вы получаете синтаксическую ошибку - вы уверены, что полученные данные не являются JSON? Тогда, может быть, вы неправильно используете API.
Другой способ, которым вы могли бы воспользоваться, но я не думаю, что это применимо в вашем случае, это иметь на странице iFrame, который находится в домене, который вы хотите вызвать. Пусть он сделает вам звонки, а затем использует JS для связи между iFrame и страницей. Это позволит обойти кросс-домен, но только если вы можете иметь src iFrame в домене, который хотите вызвать.
Вот простой способ, как вы можете это сделать, не используя ничего необычного или даже JSON.
Сначала создайте серверный скрипт для обработки ваших запросов. Что-то вроде http://www.example.com/path/handler.php
Вы будете вызывать его с параметрами, например: .../handler.php? Param1=12345¶m2=67890
Внутри него, после обработки полученных данных, выведите:
document.serverResponse('..all the data, in any format that suits you..');
// Any code could be used instead, because you dont have to encode this data
// All your output will simply be executed as normal javascript
Теперь в клиентском скрипте используйте следующее:
document.serverResponse = function(param){ console.log(param) }
var script = document.createElement('script');
script.src='http://www.example.com/path/handler.php?param1=12345¶m2=67890';
document.head.appendChild(script);
Единственным ограничением этого подхода является максимальная длина параметров, которые вы можете отправить на сервер. Но вы всегда можете отправить несколько запросов.
Вы можете использовать технологию CORS для настройки обоих серверов (сервера, на котором работает Javascript, и внешнего сервера API)
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
PS: ответ /questions/26126893/ajax-mezhdomennyij-vyizov/26126898#26126898 также предлагает этот подход, и он открывает внешний сервер API для всех остальных, чтобы он вызывал его.
Я столкнулся с той же проблемой в течение 2 дней, и я нашел решение, и оно очень элегантно после того, как много гуглил. Мне понадобился xss Ajax для некоторых клиентов виджетов, которые переносят поток данных с веб-сайтов уровней в мое приложение Rails. вот как я это сделал.