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

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

Примечания - он не должен обновлять страницу, и мне нужно получить и разобрать ответ после этого.

Комментарии к вопросу (3)

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

Если вы управляете POST-сервером, просто используйте «Стандарт межпроходного обмена ресурсами», установив заголовки ответов на сервере. Этот ответ обсуждается в других ответах в этой теме, но, на мой взгляд, не очень четко.

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

  1. В postHere.php настройка следующая:

    switch ($ _SERVER ['HTTP_ORIGIN']) {
        случай 'http://from.com': случай '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') ;
        ломать;
    }

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

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

    $ .ajax ({
        тип: «POST»
        url: 'https://to.com/postHere.php',
        crossDomain: правда
        данные: '{"некоторые": "json"} ',
        dataType: 'json',
        успех: функция (responseData, textStatus, jqXHR) {
            var value = responseData.someKey ;
        },
        error: function (responseData, textStatus, errorThrown) {
            оповещение ('POST не удалось.«);
        }
    });

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

MDN имеет отличную рецензию о HTTP-контроле доступа, в которой подробно рассказывается о том, как работает весь поток. Согласно их документам, он должен «работать в браузерах, которые поддерживают межсайтовый XMLHttpRequest». Это немного вводит в заблуждение, так как я ДУМАЮ , что только современные браузеры разрешают POST с междоменным доменом. Я только проверил, что это работает с safari, chrome, FF 3.6.

Имейте в виду следующее, если вы делаете это:

  1. Ваш сервер должен будет обрабатывать 2 запроса на операцию
  2. Вам придется подумать о последствиях для безопасности. Будьте осторожны, прежде чем делать что-то вроде «Access-Control-Allow-Origin: *»
  3. Это не будет работать в мобильных браузерах. По моему опыту, они вообще не допускают междоменную POST. Я тестировал Android, iPad, iPhone
  4. В FF & lt есть довольно большая ошибка; 3.6, где, если сервер возвращает код ответа не 400 И есть тело ответа (например, ошибки проверки), FF 3.6 не получит тело ответа. Это огромная боль в заднице, так как вы не можете использовать хорошие практики REST. См. Ошибку здесь (она подана в соответствии с jQuery, но я предполагаю, что это ошибка FF - кажется, исправлена в FF4).
  5. Всегда возвращайте заголовки выше, а не только по запросам OPTION. FF нуждается в этом в ответе от POST .
Комментарии (14)

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

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

  1. Создайте iframe с уникальным именем. (если рамы используют глобальное пространство имен для всего браузера, выберите имя, которое не будет использовать другой веб-сайт.)
  2. Создайте форму со скрытыми входами, нацеливаясь на iframe.
  3. Отправить форму.

Вот пример кода; Я протестировал его на 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 и вам необходимо использовать файлы cookie), существуют способы обойти политику одного и того же происхождения, например, с помощью window.postMessage и / или одного из ряда библиотеки, позволяющие отправлять межкадровые сообщения в старых браузерах:

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

Комментарии (15)
  1. Создайте iFrame,
  2. поместите в него форму со скрытыми входами,
  3. установите действие формы на URL,
  4. Добавить iframe в документ
  5. отправить форму

Псевдокод

 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, чтобы он был скрыт и абсолютно позиционирован. Не уверен, что браузер разрешит межсайтовый постинг, но если да, то вот как это сделать.

Комментарии (9)

Сохраняйте это простым:

  1. кросс-домен POST:
    используйте crossDomain: true,

  2. не должен обновлять страницу:
    Нет, он не будет обновлять страницу, так как обратный вызов success или error будет вызываться при отправке ответа сервером. & Лт; hr >

Пример сценария:

$.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
        }
    });
Комментарии (1)

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

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;
}

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

Комментарии (0)

Проверьте функцию post_method в http://taiyolab.com/mbtweet/scripts/twitterapi_call.js - это хороший пример для метода iframe, описанного выше.

Комментарии (0)
  1. Создайте две скрытые iframes (добавьте «отображение: нет;» в стиле css). Сделайте свой второй iframe точкой на что-то в вашем собственном домене.

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

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

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

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

Комментарии (0)

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

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

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

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

Комментарии (3)

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

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

  1. В приложении "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" = "POST, GET, OPTIONS" / >
           < / customHeaders >
       & Лт; / HttpProtocol >
  2. На «server.com» у нас будет следующее действие на контроллере (называемом «Home»), на которое мы будем публиковать:

     [HttpPost]
     публичный JsonResult Save ()
     {
         // Обработка данных поста...
    
         вернуть Json (
             новый
             {
                 IsSuccess = правда
             });
     }
  3. Затем из «caller.com» опубликуйте данные из формы (с html id «formId») на «server.com» следующим образом:

     $ .ajax ({
             тип: "POST",
             URL: "http://www.server.com/home/save",
             dataType: 'json',
             crossDomain: правда
             data: $ (formId) .serialize (),
             успех: функция (jsonResult) {
                // делать что угодно с ответом
             },
             error: function (jqXHR, textStatus) {
                 // ошибка ручки
             }
         });
Комментарии (0)

Я думаю, что лучший способ - использовать XMLHttpRequest (например,. $ .ajax (), $ .post () в jQuery) с одним из полифилов межотраслевого обмена ресурсами https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#wiki-CORS

Комментарии (0)

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

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

Это возможно, но требует координации действий между вашим и другим сервером.

Комментарии (2)

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

родитель на 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)
}
Комментарии (4)

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

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

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

http://github.com/digitalbazaar/forge

Комментарии (0)

Я знаю, что это старый вопрос, но я хотел поделиться своим подходом. Я использую 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.');
}
});
Комментарии (0)

Если у вас есть доступ к серверу междоменных ресурсов и вы не хотите вносить какие-либо изменения в код на стороне сервера, вы можете использовать библиотеку с именем - «xdomain».

Как это работает:

Шаг 1: сервер 1: включите библиотеку xdomain и настройте кросс-домен как подчиненный:

<script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>

Шаг 2: на сервере кросс-доменов создайте файл proxy.html и включите сервер 1 в качестве мастера:

proxy.html:

<script src="js/xdomain.min.js"></script>
<script>
  xdomain.masters({
    "https://server1" : '*'
  });
</script>

Шаг 3:

Теперь вы можете сделать AJAX-вызов на proxy.html в качестве конечной точки с server1. Это обход запроса CORS. Внутренняя библиотека использует решение iframe, которое работает с учетными данными и всеми возможными методами: GET, POST и т. Д.

Запрос кода ajax:

$.ajax({
        url: 'https://crossdomain_server/proxy.html',
        type: "POST",
        data: JSON.stringify(_data),
        dataType: "json",
        contentType: "application/json; charset=utf-8"
    })
    .done(_success)
    .fail(_failed)
Комментарии (0)

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

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

Комментарии (0)

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

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

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

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

Комментарии (0)