Как отправить междоменный POST-запрос с помощью JavaScript?
Примечания - он не должен обновлять страницу, и мне нужно получить и разобрать ответ после этого.
Обновление: Прежде чем продолжить, каждый должен прочитать и понять html5rocks учебник на CORS. Это легко понять и очень ясно.
Если вы управляете POST-сервером, просто используйте «Стандарт межпроходного обмена ресурсами», установив заголовки ответов на сервере. Этот ответ обсуждается в других ответах в этой теме, но, на мой взгляд, не очень четко.
Короче говоря, вот как вы выполняете кросс-домен POST от from.com/1.html до to.com/postHere.php (используя PHP в качестве примера). Примечание: вам нужно только установить Access-Control-Allow-Origin
для запросов NON OPTIONS
- этот пример всегда устанавливает все заголовки для меньшего фрагмента кода.
В 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. Это станет ясно, когда вы продолжите читать...
Настройте свой кросс-домен 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.
Имейте в виду следующее, если вы делаете это:
Если вы управляете удаленным сервером, вам, вероятно, следует использовать CORS, как описано в этом ответе; он поддерживается в IE8 и выше, а также во всех последних версиях FF, GC и Safari. (Но в IE8 и 9 CORS не позволит вам отправлять куки в запросе.)
Итак, если вы не управляете удаленным сервером, или если вам необходимо поддерживать IE7, или если вам нужны файлы cookie и вы должны поддерживать IE8 / 9, вы, вероятно, захотите использовать технику 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 и вам необходимо использовать файлы cookie), существуют способы обойти политику одного и того же происхождения, например, с помощью window.postMessage
и / или одного из ряда библиотеки, позволяющие отправлять межкадровые сообщения в старых браузерах:
Если вы не управляете удаленным сервером, вы не можете прочитать ответ POST, точка. В противном случае это вызовет проблемы с безопасностью.
Псевдокод
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, чтобы он был скрыт и абсолютно позиционирован. Не уверен, что браузер разрешит межсайтовый постинг, но если да, то вот как это сделать.
Сохраняйте это простым:
кросс-домен POST:
используйте crossDomain: true,
не должен обновлять страницу:
Нет, он не будет обновлять страницу, так как обратный вызов success
или error
будет вызываться при отправке ответа сервером.
& Лт; hr >
$.ajax({
type: "POST",
url: "http://www.yoururl.com/",
crossDomain: true,
data: 'param1=value1¶m2=value2',
success: function (data) {
// do something with server response data
},
error: function (err) {
// handle your error logic here
}
});
Если у вас есть доступ ко всем задействованным серверам, поместите в заголовок ответа следующее для запрашиваемой страницы в другом домене:
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;
}
Это, вероятно, создает проблему безопасности, и вы должны убедиться, что вы принимаете соответствующие меры для проверки запроса.
Проверьте функцию post_method
в http://taiyolab.com/mbtweet/scripts/twitterapi_call.js - это хороший пример для метода iframe, описанного выше.
Создайте две скрытые iframes (добавьте «отображение: нет;» в стиле css). Сделайте свой второй iframe точкой на что-то в вашем собственном домене.
Создайте скрытую форму, установите для ее метода значение «post» с целью = вашей первой iframe, и, при необходимости, установите для enctype значение «multipart / form-data» (я думаю, что вы хотите сделать POST, потому что вы хотите отправлять многочастные данные, такие как изображения ,?)
Когда будете готовы, сделайте форму submit () POST .
Если вы можете заставить другой домен вернуть javascript, который будет осуществлять междоменную связь с Iframes (http://softwareas.com/cross-domain-communication-with-iframes), тогда вам повезло, и вы можете получить ответ также.
Конечно, если вы хотите использовать свой сервер в качестве прокси-сервера, вы можете избежать всего этого. Просто отправьте форму на свой собственный сервер, который будет передавать запрос на другой сервер (при условии, что другой сервер не настроен для уведомления о расхождениях в IP), получите ответ и верните все, что вам нравится.
Еще одна важная вещь, чтобы отметить!!! В пример выше описано, как использовать
$.ajax({
type : 'POST',
dataType : 'json',
url : 'another-remote-server',
...
});
JQuery 1.6 и ниже имеет ошибку с кросс-доменом XHR . Согласно Firebug, никаких запросов, кроме OPTIONS, не было отправлено. Нет поста. Совсем.
Потратил 5 часов на тестирование / настройку моего кода. Добавление большого количества заголовков на удаленном сервере (скрипт). Без какого-либо эффекта. Но позже я обновил JQuery lib до 1.6.4, и все работает как шарм.
Если вы хотите сделать это в среде ASP.net MVC с 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" = "POST, GET, OPTIONS" / >
< / customHeaders >
& Лт; / HttpProtocol >
На «server.com» у нас будет следующее действие на контроллере (называемом «Home»), на которое мы будем публиковать:
[HttpPost]
публичный JsonResult Save ()
{
// Обработка данных поста...
вернуть Json (
новый
{
IsSuccess = правда
});
}
Затем из «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) {
// ошибка ручки
}
});
Я думаю, что лучший способ - использовать XMLHttpRequest (например,. $ .ajax (), $ .post () в jQuery) с одним из полифилов межотраслевого обмена ресурсами https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#wiki-CORS
Высокий уровень.... Вам необходимо настроить cname на вашем сервере таким образом, чтобы other-serve.your-server.com указывал на other-server.com.
На вашей странице динамически создается невидимый iframe, который выступает в качестве транспорта на other-server.com. Затем необходимо передать данные с помощью JS с вашей страницы на other-server.com и сделать обратные вызовы, возвращающие данные обратно на вашу страницу.
Это возможно, но требует координации действий между вашим и другим сервером.
Есть еще один способ (используя функцию 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)
}
Это старый вопрос, но некоторые новые технологии могут помочь кому-то.
Если у вас есть административный доступ к другому серверу, вы можете использовать проект Forge с открытым исходным кодом для выполнения вашего кросс-доменного POST. Forge предоставляет оболочку JavaScript XmlHttpRequest с кросс-доменом, которая использует преимущества API-интерфейса необработанных сокетов Flash. POST можно даже сделать через TLS .
Причина, по которой вам нужен административный доступ к серверу, на который вы размещаете, заключается в том, что вы должны предоставить политику междоменного доступа, которая разрешает доступ из вашего домена.
Я знаю, что это старый вопрос, но я хотел поделиться своим подходом. Я использую 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.');
}
});
Если у вас есть доступ к серверу междоменных ресурсов и вы не хотите вносить какие-либо изменения в код на стороне сервера, вы можете использовать библиотеку с именем - «xdomain».
Как это работает:
Шаг 1: сервер 1: включите библиотеку xdomain и настройте кросс-домен как подчиненный:
<script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>
Шаг 2: на сервере кросс-доменов создайте файл proxy.html и включите сервер 1 в качестве мастера:
proxy.html:
<!DOCTYPE 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)
Должно быть возможно с пользовательской таблицей YQL + JS XHR, взгляните на: http://developer.yahoo.com/yql/guide/index.html
Я использую его для очистки HTML-картинга на стороне клиента (js), работает нормально (У меня есть полный аудиоплеер, с поиском в Интернете / списках воспроизведения / текстах / последней информации fm, все клиенты js + YQL)
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 .