Как отправить запрос на междоменный POST через JavaScript?

Как отправить запрос POST через домен через JavaScript?

Заметки - он не должен обновлять страницу, и мне нужно впоследствии захватить и проанализировать ответ.

Ваша помощь с некоторыми примерами кода будет высоко оценена.

Ответ 1

Обновление:. Прежде чем продолжить, каждый должен прочитать и понять учебник html5rocks на CORS. Это легко понять и очень ясно.

Если вы управляете сервером POSTED, просто используйте "Cross-Origin Resource Sharing standard", установив заголовки ответов на сервере. Этот ответ обсуждается в других ответах в этой теме, но не очень четко, на мой взгляд.

Короче, вот как вы выполняете POST-перекрестный домен с сайта from.com/1.html на сайт to.com/postHere.php(используя PHP в качестве примера). Примечание. Вам нужно только установить Access-Control-Allow-Origin для запросов NON OPTIONS - этот пример всегда устанавливает все заголовки для меньшего фрагмента кода.

  • В настройке postHere.php выполните следующие действия:

    switch ($_SERVER['HTTP_ORIGIN']) {
        case 'http://from.com': case 'https://from.com':
        header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
        header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
        break;
    }
    

    Это позволяет вашему script выполнять кросс-домен POST, GET и OPTIONS. Это станет ясно, когда вы продолжите читать...

  • Установите свой POST-адрес кросс-домена из JS (пример jQuery):

    $.ajax({
        type: 'POST',
        url: 'https://to.com/postHere.php',
        crossDomain: true,
        data: '{"some":"json"}',
        dataType: 'json',
        success: function(responseData, textStatus, jqXHR) {
            var value = responseData.someKey;
        },
        error: function (responseData, textStatus, errorThrown) {
            alert('POST failed.');
        }
    });
    

Когда вы выполните POST на шаге 2, ваш браузер отправит на сервер метод "OPTIONS". Это "обнюхивание" браузером, чтобы узнать, прохладно ли сервер с вами, POSTing к нему. Сервер отвечает "Access-Control-Allow-Origin", сообщая браузеру "ОК" POST | GET | ORIGIN, если запрос возник из "http://from.com" или "https://from.com". Поскольку сервер в порядке с ним, браузер сделает второй запрос (на этот раз POST). Хорошей практикой является то, что ваш клиент задает тип контента, который он отправляет, - поэтому вам также необходимо это сделать.

В MDN есть отличная запись о управлении доступом HTTP, в которой подробно описывается, как работает весь поток. Согласно их документам, он должен "работать в браузерах, поддерживающих межсайтовый XMLHttpRequest". Однако это немного вводит в заблуждение, поскольку я думаю, что только современные браузеры допускают перекрестный домен POST. Я только подтвердил, что это работает с сафари, хром, FF 3.6.

Если вы это сделаете, помните следующее:

  • Серверу придется обрабатывать 2 запроса за операцию.
  • Вам придется подумать о последствиях для безопасности. Будьте осторожны, прежде чем делать что-то вроде "Access-Control-Allow-Origin: *"
  • Это не работает в мобильных браузерах. По моему опыту они вообще не допускают POST для перекрестных доменов. Я тестировал Android, iPad, iPhone.
  • В FF есть большая ошибка, 3.6 где, если сервер возвращает код ответа не 400 И есть тело ответа (например, ошибки проверки), FF 3.6 не получит тело ответа. Это огромная боль в заднице, поскольку вы не можете использовать хорошие методы REST. См. Здесь bug (его подано под jQuery, но моя догадка - это ошибка FF - кажется, исправлена ​​в FF4).
  • Всегда возвращайте заголовки выше, а не только на запросы OPTION. FF нуждается в нем в ответе от POST.

Ответ 2

Если вы управляете удаленным сервером, вы, вероятно, должны использовать CORS, как описано в этом ответе; он поддерживается в IE8 и выше, а также во всех последних версиях FF, GC и Safari. (Но в IE8 и 9 CORS не позволит вам отправлять файлы cookie в запрос.)

Итак, если вы не контролируете удаленный сервер или вам нужно поддерживать IE7, или если вам нужны файлы cookie, и вам нужно поддерживать IE8/9, вы, вероятно, захотите использовать технику iframe.

  • Создайте iframe с уникальным именем. (iframes используют глобальное пространство имен для всего браузера, поэтому выберите имя, которое не будет использовать другой веб-сайт.)
  • Построить форму со скрытыми вводами, ориентируясь на iframe.
  • Отправить форму.

Здесь пример кода; Я тестировал его на IE6, IE7, IE8, IE9, FF4, GC11, S5.

function crossDomainPost() {
  // Add the iframe with a unique name
  var iframe = document.createElement("iframe");
  var uniqueString = "CHANGE_THIS_TO_SOME_UNIQUE_STRING";
  document.body.appendChild(iframe);
  iframe.style.display = "none";
  iframe.contentWindow.name = uniqueString;

  // construct a form with hidden inputs, targeting the iframe
  var form = document.createElement("form");
  form.target = uniqueString;
  form.action = "http://INSERT_YOUR_URL_HERE";
  form.method = "POST";

  // repeat for each parameter
  var input = document.createElement("input");
  input.type = "hidden";
  input.name = "INSERT_YOUR_PARAMETER_NAME_HERE";
  input.value = "INSERT_YOUR_PARAMETER_VALUE_HERE";
  form.appendChild(input);

  document.body.appendChild(form);
  form.submit();
}

Осторожно! Вы не сможете напрямую прочитать ответ POST, поскольку iframe существует в отдельном домене. Рамам не разрешено связываться друг с другом из разных доменов; это политика одного и того же происхождения.

Если вы управляете удаленным сервером, но вы не можете использовать CORS (например, потому, что вы работаете в IE8/IE9, и вам нужно использовать куки файлы), существуют способы работы с политикой одного и того же происхождения, например, используя window.postMessage и/или один из нескольких библиотек, позволяющий отправлять междоменные межкадровые сообщения в старых браузерах:

Если вы не управляете удаленным сервером, вы не можете прочитать ответ POST, период. Это может привести к проблемам безопасности.

Ответ 3

  • Создайте iFrame,
  • введите в него форму со скрытыми входами,
  • установите действие формы в URL,
  • Добавить iframe в документ
  • отправьте форму

Псевдокод

 var ifr = document.createElement('iframe');
 var frm = document.createElement('form');
 frm.setAttribute("action", "yoururl");
 frm.setAttribute("method", "post");

 // create hidden inputs, add them
 // not shown, but similar (create, setAttribute, appendChild)

 ifr.appendChild(frm);
 document.body.appendChild(ifr);
 frm.submit();

Вероятно, вы хотите, чтобы стиль iframe был скрытым и абсолютно позиционированным. Неверная пересылка сайта разрешена браузером, но если это так, то как это сделать.

Ответ 4

Держите его простым:

  • междоменный POST:
    используйте crossDomain: true,

  • не обновлять страницу:
    Нет, он не будет обновлять страницу, так как вызов success или error async будет вызываться, когда сервер отправит ответ.


Пример script:

$.ajax({
        type: "POST",
        url: "http://www.yoururl.com/",
        crossDomain: true,
        data: 'param1=value1&param2=value2',
        success: function (data) {
            // do something with server response data
        },
        error: function (err) {
            // handle your error logic here
        }
    });

Ответ 5

Если у вас есть доступ ко всем задействованным серверам, поместите в заголовок ответа для страницы, запрашиваемой в другом домене, следующее:

PHP:

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

Например, в коде Drupal xmlrpc.php вы сделаете следующее:

function xmlrpc_server_output($xml) {
    $xml = '<?xml version="1.0"?>'."\n". $xml;
    header('Connection: close');
    header('Content-Length: '. strlen($xml));
    header('Access-Control-Allow-Origin: *');
    header('Content-Type: application/x-www-form-urlencoded');
    header('Date: '. date('r'));
    // $xml = str_replace("\n", " ", $xml); 

    echo $xml;
    exit;
}

Вероятно, это создает проблему безопасности, и вы должны убедиться, что принимаете соответствующие меры для проверки запроса.

Ответ 7

  • Создайте два скрытых iframes (добавьте "display: none;" в стиль css). Сделайте свой второй iframe точкой для чего-то в своем собственном домене.

  • Создайте скрытую форму, установите ее метод "post" с target = ваш первый iframe и, возможно, установите enctype в "multipart/form-data" (я думаю, вы хотите сделать POST, потому что хотите для отправки многостраничных данных, например изображений?)

  • Когда вы готовы, сделайте форму submit() POST.

  • Если вы можете получить другой домен для возврата javascript, который будет осуществлять междоменную связь с помощью iframe (http://softwareas.com/cross-domain-communication-with-iframes) то вам повезло, и вы также можете зафиксировать ответ.

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

Ответ 8

Еще одна важная вещь, которую нужно отметить!!! В примере выше описано, как использовать

$.ajax({
    type     : 'POST',
    dataType : 'json', 
    url      : 'another-remote-server',
    ...
});

JQuery 1.6 и ниже имеет ошибку с междоменным XHR. Согласно Firebug, никаких запросов, кроме OPTIONS, не было отправлено. Нет POST. На всех.

Отработано 5 часов тестирования/настройки моего кода. Добавление большого количества заголовков на удаленном сервере (script). Без всякого эффекта. Но позже я обновил JQuery lib до 1.6.4, и все работает как шарм.

Ответ 9

Если вы хотите сделать это в среде MVC ASP.net с помощью JQuery AJAX, выполните следующие действия: (это резюме решения, предложенного в этом потоке)

Предположим, что "caller.com" (может быть любым сайтом) необходимо отправить на "server.com" (приложение ASP.net MVC)

  • В приложении "server.com" Web.config добавьте следующий раздел:

      <httpProtocol>
          <customHeaders>
              <add name="Access-Control-Allow-Origin" value="*" />
              <add name="Access-Control-Allow-Headers" value="Content-Type" />
              <add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
          </customHeaders>
      </httpProtocol>
    
  • На "server.com" у нас будет следующее действие на контроллере (называемом "Главная" ), на которое мы будем размещать:

    [HttpPost]
    public JsonResult Save()
    {
        //Handle the post data...
    
        return Json(
            new
            {
                IsSuccess = true
            });
    }
    
  • Затем из "caller.com" отправьте данные из формы (с идентификатором html "formId" ) на "server.com" следующим образом:

    $.ajax({
            type: "POST",
            url: "http://www.server.com/home/save",
            dataType: 'json',
            crossDomain: true,
            data: $(formId).serialize(),
            success: function (jsonResult) {
               //do what ever with the reply
            },
            error: function (jqXHR, textStatus) {
                //handle error
            }
        });
    

Ответ 10

Высокий уровень.... У вас должна быть установка cname на вашем сервере, чтобы other-serve.your-server.com указывал на other-server.com.

Ваша страница динамически создает невидимый iframe, который действует как ваш транспорт на other-server.com. Затем вам необходимо связаться через JS с вашей страницы на другом сервере и получить обратные вызовы, которые возвращают данные на вашу страницу.

Возможно, но требуется координация с сайта your-server.com и other-server.com

Ответ 11

Это старый вопрос, но некоторые новые технологии могут помочь кому-то.

Если у вас есть административный доступ к другому серверу, вы можете использовать проект Forge с открытым исходным кодом, чтобы выполнить свой POST с междоменным доступом. Forge предоставляет кросс-доменную оболочку JavaScript XmlHttpRequest, которая использует API Flash raw socket. POST можно выполнить даже через TLS.

Причина, по которой вам нужен административный доступ к серверу, на который вы отправляете POST, является то, что вы должны предоставить междоменную политику, разрешающую доступ из вашего домена.

http://github.com/digitalbazaar/forge

Ответ 14

Есть еще один способ (с использованием функции html5). Вы можете использовать прокси-сервер iframe, размещенный в этом другом домене, вы отправляете сообщение с использованием postMessage в этот iframe, а затем iframe может выполнять запрос POST (в том же домене) и postMessage обратно с reposnse к родительскому окну.

parent on sender.com

var win = $('iframe')[0].contentWindow

function get(event) {
    if (event.origin === "http://reciver.com") {
        // event.data is response from POST
    }
}

if (window.addEventListener){
    addEventListener("message", get, false)
} else {
    attachEvent("onmessage", get)
}
win.postMessage(JSON.stringify({url: "URL", data: {}}),"http://reciver.com");

iframe на reciver.com

function listener(event) {
    if (event.origin === "http://sender.com") {
        var data = JSON.parse(event.data);
        $.post(data.url, data.data, function(reponse) {
            window.parent.postMessage(reponse, "*");
        });
    }
}
// don't know if we can use jQuery here
if (window.addEventListener){
    addEventListener("message", listener, false)
} else {
    attachEvent("onmessage", listener)
}

Ответ 15

Должно быть возможно с помощью пользовательской таблицы YQL + JS XHR, посмотрите: http://developer.yahoo.com/yql/guide/index.html

Я использую его, чтобы выполнить некоторую очистку HTML (js) html, отлично работает (У меня есть полный аудиоплеер, с поиском по интернету/плейлистам/текстам/последней информации fm, всем клиенту js + YQL)

Ответ 16

Я знаю, что это старый вопрос, но я хотел поделиться своим подходом. Я использую cURL как прокси-сервер, очень простой и последовательный. Создайте страницу php с именем submit.php и добавьте следующий код:

<?

function post($url, $data) {
$header = array("User-Agent: " . $_SERVER["HTTP_USER_AGENT"], "Content-Type: application/x-www-form-urlencoded");
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}

$url = "your cross domain request here";
$data = $_SERVER["QUERY_STRING"];
echo(post($url, $data));

Затем в js (jQuery здесь):

$.ajax({
type: 'POST',
url: 'submit.php',
crossDomain: true,
data: '{"some":"json"}',
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
    var value = responseData.someKey;
},
error: function (responseData, textStatus, errorThrown) {
    alert('POST failed.');
}
});

Ответ 17

CORS для вас. CORS - это "перекрестный ресурс совместного использования ресурсов", это способ отправки запроса перекрестного домена. Теперь API XMLHttpRequest2 и Fetch поддерживают CORS и могут отправлять запросы POST и GET

Но он имеет свои пределы. Серверу требуется конкретное требование Access-Control-Allow-Origin, и его нельзя установить в '*'.

И если вы хотите, чтобы любое происхождение могло отправить запрос вам, вам нужен JSONP (также нужно установить Access-Control-Allow-Origin, но может быть '*')

Для большого количества запросов, если вы не знаете, как выбрать, я думаю, вам нужен полный функциональный компонент для этого. Позвольте мне представить простой компонент https://github.com/Joker-Jelly/catta


Если вы используете современный браузер ( > IE9, Chrome, FF, Edge и т.д.), очень рекомендую вам использовать простой, но красивый компонент https://github.com/Joker-Jelly/catta. Он не имеет никакой зависимости, менее 3 КБ, и он поддерживает Fetch, AJAX и JSONP с таким же сильным синтаксическим примером и параметрами.

catta('./data/simple.json').then(function (res) {
  console.log(res);
});

Он также поддерживает весь способ импорта в ваш проект, например, модуль ES6, CommonJS и даже <script> в HTML.