tag - ¿Cómo envío una solicitud POST entre dominios a través de JavaScript?
title of page html (18)
- Crear un iFrame,
- poner un formulario en él con entradas ocultas,
- establece la acción del formulario a la URL,
- Añadir iframe al documento
- enviar el formulario
Pseudocódigo
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();
Es probable que desee diseñar el iframe, que se oculte y se coloque absolutamente. No está seguro de que el navegador permita la publicación entre sitios, pero si es así, esta es la forma de hacerlo.
¿Cómo envío una solicitud POST entre dominios a través de JavaScript?
Notas: no debería actualizar la página, y debo capturar y analizar la respuesta después.
Su ayuda con algunos ejemplos de código será muy apreciada.
Cree dos iframes ocultos (agregue "display: none;" al estilo css). Haz que tu segundo iframe apunte a algo en tu propio dominio.
Cree un formulario oculto, establezca su método en "publicar" con target = su primer iframe y, opcionalmente, configure enctype en "multipart / form-data" (creo que quiere hacer POST porque desea enviar datos multiparte como imágenes) ?)
Cuando esté listo, haga que el formulario envíe () el POST.
Si puede hacer que el otro dominio devuelva javascript que hará la Comunicación entre dominios con Iframes ( http://softwareas.com/cross-domain-communication-with-iframes ), entonces está de suerte y puede capturar la respuesta también.
Por supuesto, si desea usar su servidor como proxy, puede evitar todo esto. Simplemente envíe el formulario a su propio servidor, que enviará la solicitud al otro servidor (suponiendo que el otro servidor no esté configurado para detectar discrepancias de IP), obtenga la respuesta y devuelva lo que quiera.
CORS es para ti. CORS es "Intercambio de recursos de origen cruzado", es una forma de enviar una solicitud de dominio cruzado. Ahora, XMLHttpRequest2 y Fetch API son compatibles con CORS, y pueden enviar solicitudes POST y GET
Pero tiene sus límites. El servidor debe reclamar específicamente el acceso-control-permitir-origen , y no se puede establecer en ''*''.
Y si desea que cualquier origen pueda enviarle una solicitud, necesita JSONP (también necesita configurar Access-Control-Allow-Origin , pero puede ser ''*'')
Si no sabe cómo elegir, creo que necesita un componente funcional completo para hacerlo. Permítame presentarle un componente simple https://github.com/Joker-Jelly/catta
Si está utilizando un navegador moderno (> IE9, Chrome, FF, Edge, etc.), le recomiendo que use un componente simple pero de belleza https://github.com/Joker-Jelly/catta . No tiene dependencia, Menos de 3KB, y admite Fetch, AJAX y JSONP con la misma sintaxis y opciones de muestra mortal.
catta(''./data/simple.json'').then(function (res) {
console.log(res);
});
También admite todo el camino para importar a su proyecto, como el módulo ES6, CommonJS e incluso <script>
en HTML.
Creo que la mejor manera es usar XMLHttpRequest (por ejemplo, $ .ajax (), $ .post () en jQuery) con uno de los polyfills de intercambio de recursos entre orígenes https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#wiki-CORS
Debería ser posible con una tabla personalizada YQL + JS XHR, eche un vistazo a: http://developer.yahoo.com/yql/guide/index.html
Lo uso para hacer algunos raspados html del lado del cliente (js), funciona bien (tengo un reproductor de audio completo, con búsqueda en internet / listas de reproducción / letras / información de la última FM, todo cliente js + YQL)
Esta es una pregunta antigua, pero alguna nueva tecnología podría ayudar a alguien.
Si tiene acceso administrativo al otro servidor, entonces puede usar el proyecto OpenSource Forge para realizar su POST entre dominios. Forge proporciona un contenedor de JavaScript XmlHttpRequest de dominio cruzado que aprovecha la API de socket sin formato de Flash. El POST incluso se puede hacer sobre TLS.
La razón por la que necesita acceso administrativo al servidor al que está POSTING es porque debe proporcionar una política de dominio cruzado que permita el acceso desde su dominio.
Hay una manera más (usando la característica html5). Puede usar el iframe proxy alojado en ese otro dominio, enviar un mensaje usando postMessage a ese iframe, luego ese iframe puede hacer la solicitud POST (en el mismo dominio) y enviar el mensaje nuevamente con reposnse a la ventana principal.
padre en 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 en 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)
}
Mantenlo simple:
dominio cruzado POST:
usecrossDomain: true,
No debería actualizar la página:
No, no actualizará la página, ya que se devolverá la devolución de llamada asíncrona correcta oerror
cuando el servidor envíe la respuesta.
Ejemplo de 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
}
});
Nivel alto ... Debe tener una configuración cname en su servidor para que other-serve.your-server.com apunte a other-server.com.
Su página crea dinámicamente un iframe invisible, que actúa como su transporte a other-server.com. Luego, debe comunicarse a través de JS desde su página a other-server.com y recibir devoluciones de llamadas que devuelvan los datos a su página.
Posible, pero requiere la coordinación de your-server.com y other-server.com
Sé que esta es una vieja pregunta, pero quería compartir mi enfoque. Utilizo cURL como proxy, muy fácil y consistente. Crea una página php llamada submit.php y agrega el siguiente código:
<?
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));
Luego, en tu js (jQuery aquí):
$.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.'');
}
});
Si controla el servidor remoto, probablemente debería usar CORS, como se describe en esta respuesta ; es compatible con IE8 y superiores, y todas las versiones recientes de FF, GC y Safari. (Pero en IE8 y 9, CORS no le permitirá enviar cookies en la solicitud).
Entonces, si no controla el servidor remoto, o si tiene que ser compatible con IE7, o si necesita cookies y tiene que ser compatible con IE8 / 9, es probable que desee utilizar una técnica de iframe.
- Crea un iframe con un nombre único. (Los iframes usan un espacio de nombres global para todo el navegador, así que elija un nombre que no usará ningún otro sitio web).
- Construye un formulario con entradas ocultas, apuntando al iframe.
- Presentar el formulario.
Aquí está el código de ejemplo; Lo probé en 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();
}
¡Tener cuidado! No podrá leer directamente la respuesta del POST, ya que el iframe existe en un dominio separado. Los marcos no pueden comunicarse entre sí desde diferentes dominios; Esta es la política del mismo origen .
Si controla el servidor remoto pero no puede usar CORS (por ejemplo, porque está en IE8 / IE9 y necesita usar cookies), hay formas de evitar la misma política de origen, por ejemplo, utilizando window.postMessage
y / o una de una serie de bibliotecas que le permiten enviar mensajes entre dominios cruzados en navegadores más antiguos:
Si no controla el servidor remoto, no puede leer la respuesta del POST, punto. De lo contrario causaría problemas de seguridad.
Si desea hacer esto en el entorno MVC de ASP.net con JQuery AJAX, siga estos pasos: (este es un resumen de la solución ofrecida en this hilo)
Supongamos que "caller.com" (puede ser cualquier sitio web) debe publicar en "server.com" (una aplicación MVC de ASP.net)
En la aplicación "server.com", Web.config agrega la siguiente sección:
<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>
En "server.com", tendremos la siguiente acción en el controlador (llamada "Inicio") en la que publicaremos:
[HttpPost] public JsonResult Save() { //Handle the post data... return Json( new { IsSuccess = true }); }
Luego, desde "caller.com", publique los datos de un formulario (con el ID de html "formId") en "server.com" de la siguiente manera:
$.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 } });
Si tiene acceso a todos los servidores involucrados, coloque lo siguiente en el encabezado de la respuesta para la página que se solicita en el otro dominio:
PHP:
header(''Access-Control-Allow-Origin: *'');
Por ejemplo, en el código xmlrpc.php de Drupal harías esto:
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;
}
Esto probablemente crea un problema de seguridad, y debe asegurarse de tomar las medidas adecuadas para verificar la solicitud.
Si tiene acceso al servidor de dominios cruzados y no desea realizar ningún cambio de código en el lado del servidor, puede usar una biblioteca llamada "xdomain".
Cómo funciona:
Paso 1: servidor 1: incluye la biblioteca xdomain y configura el dominio cruzado como esclavo:
<script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>
Paso 2: en el servidor de dominios cruzados, cree un archivo proxy.html e incluya el servidor 1 como maestro:
proxy.html:
<!DOCTYPE HTML>
<script src="js/xdomain.min.js"></script>
<script>
xdomain.masters({
"https://server1" : ''*''
});
</script>
Paso 3:
Ahora, puede realizar una llamada AJAX al proxy.html como punto final desde server1. Esto es eludir la solicitud CORS. La biblioteca utiliza internamente la solución iframe que funciona con credenciales y todos los métodos posibles: GET, POST, etc.
Consulta el código 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)
Tengo un ejemplo de código para este problema.
http://reddymails.blogspot.com/2012/05/solving-cross-domain-problem-using.html
Una cosa más importante a tener en cuenta! En el example anterior se describe cómo usar
$.ajax({
type : ''POST'',
dataType : ''json'',
url : ''another-remote-server'',
...
});
JQuery 1.6 e inferior tiene un error con XHR de dominio cruzado. Según Firebug no se enviaron solicitudes, excepto OPCIONES. No POST. En absoluto.
Pasé 5 horas probando / afinando mi código. Añadiendo muchos encabezados en el servidor remoto (script). Sin ningún efecto. Pero luego, he actualizado JQuery lib a 1.6.4, y todo funciona a la perfección.
Verifique la función post_method
en http://taiyolab.com/mbtweet/scripts/twitterapi_call.js - un buen ejemplo para el método iframe descrito anteriormente.
Actualización: Antes de continuar, todos deben leer y comprender el tutorial html5rocks en CORS. Es fácil de entender y muy claro.
Si controla que el servidor esté en POST, simplemente aproveche el "estándar de Intercambio de recursos entre orígenes" estableciendo encabezados de respuesta en el servidor. Esta respuesta se discute en otras respuestas en este hilo, pero no muy claramente en mi opinión.
En resumen, aquí se muestra cómo realizar el POST de dominios cruzados de from.com/1.html a to.com/postHere.php (utilizando PHP como ejemplo). Nota: solo necesita configurar Access-Control-Allow-Origin
para las solicitudes NO OPTIONS
: este ejemplo siempre establece todos los encabezados para un fragmento de código más pequeño.
En la configuración postHere.php lo siguiente:
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; }
Esto permite que su script realice dominios cruzados POST, GET y OPTIONS. Esto quedará claro a medida que continúe leyendo ...
Configure su dominio POST de JS (ejemplo de 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.''); } });
Cuando realice el POST en el paso 2, su navegador enviará un método de "OPCIONES" al servidor. Este es un "sniff" por el navegador para ver si el servidor está bien con usted POSTing. El servidor responde con un "Access-Control-Allow-Origin" indicando que el navegador está bien para POST | GET | ORIGIN si la solicitud se originó en " http://from.com " o " https://from.com ". Dado que el servidor está de acuerdo con esto, el navegador realizará una segunda solicitud (esta vez un POST). Es una buena práctica que su cliente establezca el tipo de contenido que está enviando, por lo que también deberá permitirlo.
MDN tiene una gran reseña sobre el control de acceso HTTP , que se detalla en cómo funciona todo el flujo. Según sus documentos, debe "funcionar en navegadores que admitan XMLHttpRequest entre sitios". Sin embargo, esto es un poco engañoso, ya que PIENSO que solo los navegadores modernos permiten POST entre dominios. Solo he verificado que esto funciona con safari, chrome, FF 3.6.
Tenga en cuenta lo siguiente si hace esto:
- Su servidor tendrá que manejar 2 solicitudes por operación.
- Tendrá que pensar en las implicaciones de seguridad. Tenga cuidado antes de hacer algo como ''Access-Control-Allow-Origin: *''
- Esto no funcionará en los navegadores móviles. En mi experiencia, no permiten POST de dominio cruzado en absoluto. He probado Android, iPad, iPhone
- Hay un error bastante grande en FF <3.6 donde, si el servidor devuelve un código de respuesta no 400 Y hay un cuerpo de respuesta (errores de validación, por ejemplo), FF 3.6 no obtendrá el cuerpo de la respuesta. Este es un gran dolor en el culo, ya que no se pueden usar buenas prácticas de REST. Vea el error here (está archivado en jQuery, pero mi conjetura es que es un error FF - parece estar arreglado en FF4).
- Siempre devuelva los encabezados arriba, no solo en las solicitudes de OPCIÓN. FF lo necesita en la respuesta del POST.