Как отправить запрос на междоменный 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¶m2=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;
}
Вероятно, это создает проблему безопасности, и вы должны убедиться, что принимаете соответствующие меры для проверки запроса.
Ответ 6
Проверьте функцию post_method
в http://taiyolab.com/mbtweet/scripts/twitterapi_call.js - хороший пример описанного выше метода iframe.
Ответ 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
Ответ 12
Я думаю, что лучший способ - использовать XMLHttpRequest (например, $.ajax(), $.post() в jQuery) с одним из полиномов совместного использования ресурсов Cross-Origin https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#wiki-CORS
Ответ 13
У меня есть пример кода для этой проблемы.
http://reddymails.blogspot.com/2012/05/solving-cross-domain-problem-using.html
Ответ 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.