Ajax на другой сервер. Отправка ajax-запроса на другой домен. Пробуем получить данные с другого домена

Синтаксис и описание:

Возвращаемое значение: Экземпляр объекта XHR (XMLHttpRequest).

Параметры:

    options – (объект) Объект в виде набора свойств (пар ключ:"значение"), которые задают параметры для Ajax запроса. Возможных параметров (свойств объекта options) очень много, и обычно в большинстве случаев они используются далеко не все, а только некоторые из них. К тому же, все эти параметры являются необязательными, т.к. значение любого из них может быть установлено по умолчанию с помощью метода $.ajaxSetup() .

    Для настройки Ajax-запроса доступны следующие свойства объекта options:

    • async – (boolean - логическое значение) По умолчанию имеет значение true, и тогда все запросы выполняются асинхронно (На то он и Ajax, чтобы операции выполнялись параллельно). Если установить зхначение false, что крайне нежелательно, то запрос будет выполняеться как синхронный (Другие действия браузера могут блокироваться на время, пока выполняется синхронный запрос. Да и вообще браузер может перестать реагировать и отвечать).

      beforeSend(XHR ) – (функция) Функция, вызываемая перед отправкой запроса. Она используетсядля установки дополнительных (пользовательских) заголовков или для выполнения других предварительных операций. В качестве единственного аргумента ей передается экземпляр объекта XHR (XMLHttpRequest). Если функция возвращает ложное значение (false), то происходит отмена запроса.

      cache – (boolean - логическое значение) Если имеет значение false, то запрашиваемые страницы не кэшируются браузером. (Браузер может выдавать результаты из кэша. Например, когда данные в ответе сервера на Ajax запрос всегда новые, то кеширование мешает). По умолчанию имеет значение true для типов данных text, xml, html, json. Для типов данных "script" и "jsonp" имеет значение по умолчанию false.

      complete(XHR, textStatus ) – (функция) Функция, вызываемая по окончании запроса независимо от его успеха или неудачи (а также после функций success и error, если они заданы). Функция получает два аргумента: экземпляр объекта XHR (XMLHttpRequest) и строку, сообщающую о состоянии "success" или "error" (в соответствии с кодом статуса в ответе на запрос).

      contentType – (строка) Тип содержимого в запросе (при передаче данных на сервер). По умолчанию имеет значение "application/x-www-form-urlencoded" (подходит для большинства случаев и используется по умолчанию также при отправке форм).

      context – (объект) Данный объект станет контекстом (this) для всех функций обратного вызова, связанных с данным Ajax-запросом (например, для функций success или error).

      $.ajax({ url: "test.html",
      context: document.body,
      success: function(){
      $(this).addClass("done");
      }});

      data – (строка | объект) Данные, отправляемые c запросом на сервер. Они преобразовываются в строку запроса и по умолчанию обязательно кодируются в URL-подобный вид (За автоматическое кодирование в формат URL отвечает параметр processData).

      Строка присоединяется к строке запроса URL, если запрос выполняется методом GET. Если же запрос выполняется методом POST, то данные передаются в теле запроса.

      Если данный параметр является объектом в виде набора пар имя_свойства/значение, а значение является массивом, то jQuery сериализует объект в последовательность нескольких значений с одним и тем же ключом.

      Например, {Foo: [ "bar1", "bar2"]} станет "&Foo=bar1&Foo=bar2" .

      dataFilter(data, type ) – (функция) Функция, которая вызывается в случае успеха запроса и используется для обработки данных, полученных в ответе сервера на запрос. Она возвращает данные, обработанные в соответствии с параметром "dataType", и передает их функции success. Данные типа text и xml передаются без обработки сразу функции success через свойство responseText или responseHTML объекта XMLHttpRequest. Функция dataFilter получает два аргумента:

    • data - полученные данные (тело ответа сервера),
    • type - тип этих данных (параметр "dataType").
    • dataType – (строка) Строка, определяющая название типа даных, ожидаемых в ответе сервера. Если тип данных не задан, jQuery сама пытается его определить, ориентируясь на MIME-тип ответа сервера. Допустимые значения:"xml", "html", "script", "json", "jsonp", "text". (Это необходимо для того, чтобы определить метод обработки данных, полученных в ответе на запрос, функцией dataFilter перед тем, как они будут переданы функции обратного вызова success.)

      error(XHR, textStatus, errorThrown ) – (функция) Функция , которая вызывается при неудачном запросе (если код статуса в ответе сервера сообщает об ошибке). Функции передаются три аргумента:

    • XHR - экземпляр объекта XMLHttpRequest,
    • textStatus - строка, описывающая тип ошибки, которая произошла ("timeout", "error", "notmodified" или "parsererror"),
    • errorThrown - необязательный параметр – объект-исключение, если таковой имеется (возвращается экземпляром объекта XHR).
    • global – (boolean - логическое значение) По умолчанию имеет значение true (разрешен вызов глобальных обработчиков событий на различных этапах Ajax-запроса, например, функций ajaxStart или ajaxStop). Значение false устанавливается, чтобы предотвратить их срабатывание. (Используется для управления Ajax-событиями).

      ifModified – (boolean - логическое значение) Если установлено значение true, то запрос считается успешным только в том случае, если данные в ответе изменились с момента последнего запроса (jQuery определяет, совпадает ли компонент в кэше браузера с тем, что находится на сервере, путем проверки заголовка "Last-Modified" с датой последней модификации содержимого, а в jQuery 1.4 также проверяется заголовок "Etag" – строка с версией компонента). По умолчанию имеет значение false, т.е. успешность запроса не зависит от заголовков и от изменений в ответе.

      jsonp – (строка) Переопределяет имя функции обратного вызова для кроссдоменного запроса jsonp. Заменяет собой ключевое слово callback в части "callback=?" строки GET запроса (добавляемой к URL) или передаваемой в теле запроса при передаче методом POST. По умолчанию jQuery автоматически генерирует уникальное имя для функции обратного вызова.

      jsonpCallback – (строка) Определяет имя функции обратного вызова для jsonp-запроса. Это значение будет использоваться вместо случайного имени, автоматически генерируемого библиотекой jQuery. Использование данного параметра позволяет избегать пропусков кэширования браузером GET запросов. Желательно разрешать jQuery генерировать новое имя для каждого нового кроссдоменного запроса на сервер для удобства управления запросами и ответами.

      password – (строка) Пароль, который будет использоваться в ответ на требование HTTP авторизации на сервере.

      processData – (boolean - логическое значение) По умолчанию имеет значение true, и данные, передаваемые на сервер в параметре data, преобразовываются в строку запроса с типом содержимого "Application / X-WWW-форм-urlencoded" и кодируются. Если такая обработка нежелательна (когда необходимо отправить на сервер другие данные, например DOMDocument или объект xml), то ее можно обойти, установив для данного параметра значение false.

      scriptCharset – (строка) При выполнении запросов методом GET и запросов, ориентированных на получение данных типа "jsonp" или "script", указывает кодировку символов запроса (например "UTF-8" или "CP1251"). Полезно при различиях между кодировками на стороне клиента и на серверной стороне.

      success(data, textStatus, XHR ) – (функция) Функция, которая вызывается при успешном запросе (если код статуса в ответе на запрос сообщает об успехе). Функции передаются три аргумента:

    • data - данные, возвращаемые сервером в ответе, предварительно обработанные функцией dataFilter в соответствии со значением параметра dataType,
    • textStatus - строку с кодом статуса, сообщающем об успехе,
    • XHR - экземпляр объекта XMLHttpRequest.
    • timeout – (число) Устанавливает максимальное время ожидания ответа сервера в милисекундах. Имеет приоритет над глобальной установкой предельного времени ожидания через $.AjaxSetup. Если лимит времени ожидания превышен, то выполнение запроса прерывается и вызывается функция обработки ошибок error (если она установлена). Это можно использовать, например, для того, чтобы назначить определенному запросу более длительное время ожидания, чем время, установленное для всех запросов.

      traditional – (boolean - логическое значение) Необходимо установить значение true, чтобы использовать традиционную (упрощенную) сериализацию (преобразование) данных при отправке (без рекурсивного преобразования в URL-подобную строку объектов или массивов, которые вложены в другие массивы или объекты).

      type – (строка) HTTP-метод передачи данных при выполнении запроса. По умолчанию данные передаются методом GET. Обычно используются GET или POST. Также можно использовать методы PUT и DELETE, но это не рекомендуется, ввиду того, что они поддерживаются не всеми браузерами.

      url – (строка) Строка, содержащая URL-адрес, по которому посылается запрос. По умолчанию это текущая страница.

      username – (строка) Имя пользователя, которое будет использоваться для HTTP авторизации на сервере.

      xhr – (функция) Функция, вызываемая для создания экземпляра объекта XMLHttpRequest. По умолчанию создание объекта XHR реализовано через ActiveXObject в браузере IE, либо через встроенный объект типа XMLHttpRequest в остальных случаях.

  • // Выполнить асинхронный Ajax-запрос с помощью метода POST. // Отправить данные на сервер и в случае успеха вывести // ответ сервера в диалоговом окне. $.ajax({ type: "POST", url: "test.php", data: "name=John&location=Boston", success: function(msg){ alert("Data Saved: " + msg); } });



  • Запрос на http://name.my/ajax.php (буду писать везде php, чтобы всем было удобно, сам же работал с java) вернет нам ответ без проблем
  • Запрос на http://google.com/ завершится ошибкой доступа
  • Попытка достучаться до https://name.my/ajax.php тоже окончится неудачей, сменился протокол
  • http://name.my:81/ajax.php и другой порт в адресе испортит малину
  • Задача: найти кроссбраузерное решение для отправки запросов которое будет работать: ie7+, opera 9.6+, ff 3+, chrome, safari. А также так как обращаться мне приходилось также с http на https не должно быть сообщения “mixed content” в ie.
    В качестве библиотеки на сайте использовалась jQuery и встроенного механизма кросс доменных запросов в ней нет (появилася в 1.5 возможность организовать jsonp но это не всегда подходит), поиск плагинов также не дал результатов. Поэтому, обломавшись с простыми путями (что в принципе и ожидалось), отправился в Google, который тоже не дает очевидного ответа - я больше находил описание методов или же вещи которые мне не подходили (например в dojo есть релизая таких запросов, но менять весь js на сайте очень трудозатратно).
    В качестве решения проблемы могли бы использоваться следующие техники:
  • postMessage
  • JSONP
  • document.domain methods
  • window.name Transport
  • Server-side proxy
  • CRAZY IFRAME STUFF
  • flash
  • Новичок, при виде этого списка ужаснётся (в принципе я тоже не в восторге был). Итак наша задача - найти оптимальный путь решения проблемы, который не создавал бы лишних костылей на сайте.
    1) postMessage – это новая возможность стандарта HTML5, позволяет отсылать сообщения из одного окна в другое, при этом контент окон может быть с разных доменов. Примерная реализация targetWindow.postMessage(message, targetOrigin); targetWindow - окно куда шлём запроc, message - сообщение, targetOrigin целевой домен который должен быть открыт в окне, допускается указания “*” в качестве домена, при этом домен может быть любой.
    2) JSONP (JSON Padding) или «JSON с подкладкой» является расширением JSON, когда имя функции обратного вызова указывается в качестве входного аргумента. Использовав тэг, мы можем обратиться к другим доменам, однако результат придет в виде json ответа, который мы не сможем обработать, jsonp предлагает следующее решение: передавая серверу имя функции, мы получаем в ответе не голые данные, а parseResponse({«paper»: «A4», «count»: 5}), что вызовет функцию parseResponse.
    3)CORS тема большая, поэтому расскажу вкратце, кому интересно велкам в w3c документацию. XMLHTTPRequest 2 - это новая спецификация запросов, работает и вызывается как обычный XMLHTTPRequest (в ie это XDomainRequest), но теперь в http заголовок добавляется следующее:
    Access-Control-Allow-Origin определяет каким доменам разрешено соединение
    Access-Control-Allow-Credentials указывает полномочия на выполнения запроса (Access-Control-Allow-Credentials: «Access-Control-Allow-Credentials» ":" true true: %x74.72.75.65; «true», case-sensitive)
    Access-Control-Max-Age - как долго результаты будут кэшироваться.
    Также можно определить доступные методы (GET, POST), все дополнительные поля заголовка вы можете посмотреть в спецификации.
    Главная проблема метода - его поддерживают далеко не все браузеры, а тем кто захотят использовать реализация от IE - XDomainRequest, не стоит забывать, что IE в своем репертуаре и не позволит вам сделать запрос с протокола http на https, хотя по спецификации запрещены только запросы с https на http), но это ie.
    4) document.domain нам подойдет, если мы хотим общаться с 2 сайтами на общем наддомене, то есть test1.name.my и test2.name.my. Между этими сайтами нормальный запрос не сделать, однако у document есть свойство domain, которое мы можем сменить для обоих окон на name.my и общаться обычным способом через iframe.
    5) window.name Transport - заключается в изменении свойста name у windows и передачи таким образом через текст свойства наших сериализованных данных.
    6) Server-side proxy - самое простое решение - это проксирование запроса сервером. То есть, name.my делает специальный запрос, например, на особенный URL типа name.my/proxy/name2.my/test.html , и сервер name.my проксирует его на name2.my/test.html .
    7) CRAZY IFRAME STUFF - суть метода в том, что ифреймы, даже находясь на разных доменах, могут общаться друг с другом при помощи изменения идентификаторов фрагментов адресов (идентификатор – то, что стоит в адресе после "#") Путем последовательных изменений #фрагмента образуется поток данных, который может передаваться в обе стороны. Т.к идентификатор фрагмента - текст, то все данные для передачи приходится (де)сериализовать, т.е превращать в JSON + понадобится 2 iframe, дабы не затрагивать адрес видимого окна.
    8) flash - использовать флеш в качестве промежуточного интерфейса (отдельная тема, все тонкости которой также тянут на статью)
    Поискав в интернете нашел замечательную библиотеку easyxdm.net/wp . Самое вкусное заключается в методе работы, выбирается самый быстрый и современные метод основываясь на браузере и его версии.
    • IE6 and IE7 – используется связка с флешем (Microsoft Security Bulletin MS11-018)
    • IE8+ – используется postMessage
    • Opera 9+ – используется postMessage
    • Firefox 1-2 – используются ifame
    • Firefox 3+ – используется postMessage
    • Safari 4+ – используется postMessage
    • Chrome 2+ – используется postMessage
    Для остальных браузеров которые не поддерживают postMessage будет использоваться технология основанная на обмене #hash Функции библиотеки не ограничиваются только ajax но разговор будет в основном о нем.
    Итак начну c реализации ajax запроса при помощью easyxdm.
    Создаем непосредственно прокси объект для отсылки запросов:
    var xhr = new easyXDM.Rpc({ remote: "http://name.my/cors/index.html" // путь к провайдеру }, { remote: { request: {} } });

    EasyXDM – это, если так можно назвать статический класс, который не имеет конструктора и реализует паттерн синглтон.
    Шлем сам запрос:
    xhr.request({ url: "pathRelativeToRemote/getrest/", //адрес нашего запроса method: "POST", data: {foo:"bar"} }, function(response) { // функция обработки результата ответа alert(response.status); alert(response.data); });

    Теперь более подробно: первым параметром мы задаем основные настройки, в частности тут указываем путь к заранее подготовленному файлу “провайдеру” (лежит в архиве с сборкой в папке cors), который должен находи

    Я на удаленном сервере, он будет проксировать запросы на нужный нам url и посылать нам ответы одним из доступных методов.
    Однако не стоит забывать что сюда также надо будет вписать путь до флешки (флешка также прикладывается к либе), через которую будут устанавливать соединение старые версии IE.

    Далее мы создаем структуру удаленных методов, сейчас там объявлен request (в файле name.my/cors/index.html также должна быть создана аналогичная структура методов)
    Вызовом функции xhr.request мы отсылаем запрос нашему прокси файлу name.my/cors/index.html , который стучится по url и передает туда параметр data , используя обычный ajax, получив ответ, он шлёт данные (при необходимости разбивая ответ на части) обратно к нашему хосту, где вызывается callback, который мы передали последним параметром.
    Немного затронем файл name.my/cors/index.html он является незаменимой частью нашего запроса, во-первых он организует обратный транспорт и прием данных. Во вторых у него есть замечательная плюшка - он реализует CORS своими средствами:
    var useAccessControl = true; // разрешаем (true) или запрещаем (false) принимать заголовки от сервера (чтобы случайно сервером не разрешить отсылку данных на сторонний домент)
    var alwaysTrustedOrigins = [(/\.?easyxdm\.net/), (/xdm1/)]; // список разрешенных серверов
    var remote - объект easyXDM, в котором мы должны реализовать структуру удаленных методов.

    А также не забываем подключать маленькую “библиотечку” json2.js которая для старых браузером реализует объект JSON, активно использующийся в easyXDM (при этом easyXDM не мешает вам создать свой сериализатор и передать его в качестве параметра, хотя мне кажется это очень редкая потребность).

    У меня в проекте стояла задача слать по аяксу много разных форм, соответственно нужен был удобный инструмент который сериализует и шлет по ajax указанную форму. Выход нашелся сразу в лице плагина jQuery Form, но плагин завязан на jq и следовательно слать кросс доменные запросы отказывается.
    Приведу простой способ как внедрить наш кросс доменный запрос в плагин не затронув структуры и оставив jQuery в качестве обработчика обычного ajax.
    Имеем в html форму (то что внутри формы нас мало волнует этим займется плагин):
    ...
    Заранее подготовим наш объект для кросс доменного запроса:
    crossAjax = new easyXDM.Rpc({ remote: "name2.my/cors", // наш провайдер на удаленном сервере swf: "name.my/easyxdm.swf" }, { remote: { request: {} } });

    Далее приведен код подключения плагина, в котором все поля формы автоматически сериализуются, а url на который мы шлем форму берется из action самой формы (как и метод)
    $("#myform").ajaxForm({ beforeSubmit: beforeSubmit, success: showResponse });

    Это метод в котором мы обрабатываем результат, его мы вообще не затрагиваем:
    showResponse = function(responseText, statusText, xhr, form){ тут мы что-то делаем с нашим ответом }

    А вот главный фокус будет в beforeSubmit, метод вызывается перед отправкой формы, соответственно тут мы можем как получить уже сериализованные данные так и прервать дальнейшую отправку запроса (что нам и надо):
    beforeSubmit = function(arr, form, options) { if (options.url.indexOf(location.host) function testAjax(id, pid) { $.ajax({ type: "POST", data: "id=" + id + "&pid=" + pid, url: "/path/to/script/test.php", success: function(data) { $("#content").html(data); } }); return true; } Успешный запрос
    Запрос с ошибкой

    Ответ:

    PHP скрипт (test.php):


    Больше информации можно посмотреть по адресу: http://api.jquery.com/jquery.ajax/

    Иногда бывает нужно отправить ajax-запрос на другой домен , чтобы динамически подгрузить оттуда данные. Однако, ajax этого сделать не позволяет в целях безопасности. Но в этой статье я покажу, как это ограничение можно обойти.

    В основе лежит то, что хоть ajax и не позволяет отправлять запрос на другой домен, но PHP позволяет отправлять что угодно и куда угодно. Итак, алгоритм следующий:

  • Отправить ajax-запрос скрипту на нашем домене.
  • Скрипт на нашем домене отправляет любые запросы на другой домен и получает от него ответ, возвращая его.
  • ajax принимает ответ от нашего скрипта с ответом от другого домена.
  • Вот такой простой алгоритм. Давайте его быстренько реализуем. Значит, сразу ajax :


    /* Данная функция создаёт кроссбраузерный объект XMLHTTP */
    function getXmlHttp() {
    var xmlhttp;
    try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
    try {
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (E) {
    xmlhttp = false;
    }
    }
    if (!xmlhttp && typeof XMLHttpRequest!="undefined") {
    xmlhttp = new XMLHttpRequest();
    }
    return xmlhttp;
    }
    function send() {
    var xmlhttp = getXmlHttp(); // Создаём объект XMLHTTP
    xmlhttp.open("POST", "test.php", true); // Открываем асинхронное соединение
    xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // Отправляем кодировку
    xmlhttp.send("site=" + encodeURIComponent("http://ya.ru/?a=5")); // Отправляем POST-запрос
    xmlhttp.onreadystatechange = function() { // Ждём ответа от сервера
    if (xmlhttp.readyState == 4) { // Ответ пришёл
    if(xmlhttp.status == 200) { // Сервер вернул код 200 (что хорошо)
    document.getElementById("yandex").innerHTML = xmlhttp.responseText; // Выводим ответ сервера
    }
    }
    };
    }




    А теперь файл test.php , который и занимается отправкой запроса на другой домен:

    Всё, теперь при нажатии на кнопку "Отправить " у Вас будет открываться страница "http://ya.ru/?a=5 ". Как видите, отправить ajax-запрос на другой домен не составляет никакого труда.