Come invio una richiesta POST tra domini tramite JavaScript?

Come invio una richiesta POST tra domini tramite JavaScript?

Note: non dovrebbe aggiornare la pagina, e ho bisogno di afferrare e analizzare la risposta in seguito.

Il tuo aiuto con alcuni esempi di codice sarà molto apprezzato.

Aggiornamento: prima di continuare, tutti dovrebbero leggere e comprendere il tutorial html5rocks su CORS. È facile da capire e molto chiaro.

Se si controlla il server sottoposto a POST, è sufficiente sfruttare lo “standard di condivisione delle risorse Cross-Origin” impostando le intestazioni di risposta sul server. Questa risposta è discussa in altre risposte in questa discussione, ma non molto chiaramente secondo me.

In breve, ecco come si realizza il POST cross domain da from.com/1.html a to.com/postHere.php (usando PHP come esempio). Nota: è sufficiente impostare Access-Control-Allow-Origin per le richieste NON OPTIONS : in questo esempio vengono sempre impostate tutte le intestazioni per uno snippet di codice più piccolo.

  1. Nella configurazione di 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; } 

    Ciò consente al tuo script di eseguire test POST, GET e OPZIONI su più domini. Questo diventerà chiaro mentre continui a leggere …

  2. Imposta il tuo POST cross-domain da JS (esempio 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.'); } }); 

Quando esegui il POST al punto 2, il tuo browser invierà un metodo “OPTIONS” al server. Questo è un “annusare” dal browser per vedere se il server è bello con il POST a farlo. Il server risponde con un “Access-Control-Allow-Origin” che dice al browser che è OK a POST | GET | ORIGIN se la richiesta proviene da ” http://from.com ” o ” https://from.com “. Poiché il server funziona correttamente, il browser eseguirà una seconda richiesta (questa volta un POST). È buona prassi che il tuo cliente imposti il ​​tipo di contenuto che sta inviando, quindi dovrai permetterlo anche a questo.

MDN ha una grande recensione sul controllo degli accessi HTTP , che va nel dettaglio di come funziona l’intero stream. Secondo i loro documenti, dovrebbe “funzionare nei browser che supportano XMLHttpRequest cross-site”. Questo è un po ‘fuorviante, tuttavia, poiché penso che solo i browser moderni consentano il POST cross-domain. Ho solo verificato che funzioni con safari, chrome, FF 3.6.

Tieni presente quanto segue se lo fai:

  1. Il tuo server dovrà gestire 2 richieste per operazione
  2. Dovrai pensare alle implicazioni sulla sicurezza. Fai attenzione prima di fare qualcosa come “Access-Control-Allow-Origin: *”
  3. Questo non funzionerà con i browser mobili. Secondo la mia esperienza, non consentono affatto il POST cross-domain. Ho testato Android, iPad, iPhone
  4. C’è un bug piuttosto grande in FF <3.6 dove se il server restituisce un codice di risposta non 400 E c'è un corpo di risposta (errori di validazione per esempio), FF 3.6 non otterrà il corpo della risposta. Questo è un enorme rompicoglioni, dal momento che non puoi usare buone pratiche di REST. Vedi bug qui (è archiviato sotto jQuery, ma suppongo che sia un bug FF - sembra essere stato risolto in FF4).
  5. Restituisci sempre le intestazioni sopra, non solo sulle richieste OPTION. FF ne ha bisogno nella risposta dal POST.

Se controlli il server remoto, dovresti probabilmente usare CORS, come descritto in questa risposta ; è supportato in IE8 e versioni successive e tutte le versioni recenti di FF, GC e Safari. (Ma in IE8 e 9, CORS non ti consentirà di inviare cookie nella richiesta.)

Quindi, se non controlli il server remoto, o se devi supportare IE7, o se hai bisogno di cookie e devi supportare IE8 / 9, probabilmente vorrai usare una tecnica iframe.

  1. Crea un iframe con un nome univoco. (Gli iframe utilizzano uno spazio dei nomi globale per l’intero browser, quindi scegli un nome che nessun altro sito Web utilizzerà.)
  2. Costruisci un modulo con input nascosti, mirando all’iframe.
  3. Invia il modulo.

Ecco il codice di esempio; L’ho provato su 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(); } 

Attenzione! Non sarai in grado di leggere direttamente la risposta del POST, poiché l’iframe esiste in un dominio separato. I frame non sono autorizzati a comunicare tra loro da domini diversi; questa è la stessa politica di origine .

Se controlli il server remoto ma non puoi usare CORS (ad esempio perché sei su IE8 / IE9 e devi usare i cookie), ci sono modi per aggirare la politica dell’origine stessa, ad esempio usando window.postMessage e / o una delle numerose librerie che consente di inviare messaggi cross-frame cross-frame nei browser più vecchi:

  • Oblò
  • XSSInterface
  • EasyXDM
  • jQuery PostMessage Plugin

Se non si controlla il server remoto, non è ansible leggere la risposta del POST, punto. In caso contrario, causerebbe problemi di sicurezza.

  1. Crea un iFrame,
  2. mettere un modulo in esso con input nascosti,
  3. imposta l’azione del modulo sull’URL,
  4. Aggiungi iframe al documento
  5. invia il modulo

pseudocodice

  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(); 

Probabilmente vuoi modellare l’iframe, essere nascosto e posizionato in modo assoluto. Non è sicuro che la pubblicazione sul sito sia consentita dal browser, ma se è così, questo è come farlo.

Resta semplice:

  1. POST tra domini:
    usa crossDomain: true,

  2. non dovrebbe aggiornare la pagina:
    No, non aggiornerà la pagina quando verrà richiamata la chiamata asincrona di success o di error quando il server invierà la risposta.


Script di esempio:

 $.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 } }); 

Se hai accesso a tutti i server coinvolti, inserisci quanto segue nell’intestazione della risposta per la pagina richiesta nell’altro dominio:

PHP:

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

Ad esempio, nel codice xmlrpc.php di Drupal si dovrebbe fare questo:

 function xmlrpc_server_output($xml) { $xml = ''."\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; } 

Ciò probabilmente crea un problema di sicurezza e dovresti assicurarti di prendere le misure appropriate per verificare la richiesta.

Controlla la funzione post_method in http://taiyolab.com/mbtweet/scripts/twitterapi_call.js – un buon esempio per il metodo iframe descritto sopra.

  1. Crea due iframe nascosti (aggiungi “display: none;” allo stile css). Fai in modo che il secondo iframe punti a qualcosa sul tuo dominio.

  2. Crea un modulo nascosto, imposta il suo metodo su “post” con target = il tuo primo iframe e opzionalmente imposta enctype su “multipart / form-data” (sto pensando di voler fare il POST perché vuoi inviare dati multipart come le immagini ?)

  3. Una volta pronto, invia il modulo submit () al POST.

  4. Se è ansible ottenere l’altro dominio per restituire javascript che farà Cross-Domain Communication With Iframes ( http://softwareas.com/cross-domain-communication-with-iframes ) allora si è fortunati e si può catturare la risposta anche.

Naturalmente, se si desidera utilizzare il server come proxy, è ansible evitare tutto ciò. Invia semplicemente il modulo al tuo server, che invierà la richiesta all’altro server (supponendo che l’altro server non sia configurato per notare discrepanze IP), ottieni la risposta e restituisci quello che vuoi.

Una cosa più importante da notare !!! Nell’esempio sopra è descritto come usare

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

JQuery 1.6 e precedenti ha un bug con XHR interdominio. Secondo Firebug non sono state inviate richieste eccetto OPZIONI. Nessun post. Affatto.

Ho trascorso 5 ore di test / tuning del mio codice. Aggiunta di molte intestazioni sul server remoto (script). Senza alcun effetto Ma più tardi, ho aggiornato la lib di JQuery alla 1.6.4, e tutto funziona come un incantesimo.

Se si desidera eseguire ciò nell’ambiente MVC ASP.NET con JQuery AJAX, attenersi alla seguente procedura: (questo è un riepilogo della soluzione offerta in questo thread)

Supponiamo che “caller.com” (qualsiasi sito web) debba essere pubblicato su “server.com” (un’applicazione ASP.net MVC)

  1. Sul Web.config dell’app “server.com” aggiungi la seguente sezione:

             
  2. Sul “server.com”, avremo la seguente azione sul controller (chiamata “Home”) a cui pubblicheremo:

     [HttpPost] public JsonResult Save() { //Handle the post data... return Json( new { IsSuccess = true }); } 
  3. Quindi dal “caller.com”, invia i dati da un modulo (con l’id html “formId”) a “server.com” come segue:

     $.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 } }); 

Livello alto …. È necessario avere una configurazione cname sul server in modo che other-serve.your-server.com punti ad other-server.com.

La tua pagina crea dynamicmente una iframe invisibile, che funge da trasporto verso other-server.com. Quindi devi comunicare tramite JS dalla tua pagina a other-server.com e avere richiamate che restituiscono i dati alla tua pagina.

Possibile ma richiede il coordinamento da your-server.com e other-server.com

Questa è una vecchia domanda, ma alcune nuove tecnologie potrebbero aiutare qualcuno.

Se si dispone dell’accesso amministrativo all’altro server, è ansible utilizzare il progetto Forza opensource per completare il POST interdominio. Forge fornisce un wrapper XmlHttpRequest JavaScript interdominio che sfrutta l’API raw socket di Flash. Il POST può anche essere eseguito su TLS.

Il motivo per cui è necessario l’accesso amministrativo al server su cui si sta posticipando è perché è necessario fornire un criterio interdominio che consenta l’accesso dal proprio dominio.

http://github.com/digitalbazaar/forge

Penso che il modo migliore sia usare XMLHttpRequest (ad es. $ .Ajax (), $ .post () in jQuery) con uno dei polifreni di condivisione delle risorse di Cross-Origin https://github.com/Modernizr/Modernizr/wiki/HTML5- Cross-Browser-polyfills # wiki-CORS

C’è un altro modo (usando la funzionalità html5). È ansible utilizzare iframe proxy ospitato su quell’altro dominio, inviare un messaggio utilizzando postMessage a tale iframe, quindi quell’iframe può eseguire la richiesta POST (sullo stesso dominio) e postMessage con reposnse alla finestra padre.

genitore su 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 su 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) } 

Dovrebbe essere ansible con una tabella personalizzata YQL + JS XHR, dare un’occhiata a: http://developer.yahoo.com/yql/guide/index.html

Lo uso per fare alcuni client (js) html scraping, funziona bene (ho un lettore audio completo, con ricerca su internet / playlist / testi / ultime informazioni fm, tutti i client js + YQL)

So che questa è una domanda vecchia, ma volevo condividere il mio approccio. Uso cURL come proxy, molto semplice e coerente. Crea una pagina php chiamata submit.php e aggiungi il seguente codice:

  

Quindi, nella tua js (jQuery qui):

 $.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.'); } }); 

CORS è per te. CORS è “Cross Origin Resource Sharing”, è un modo per inviare una richiesta cross domain.Ora XMLHttpRequest2 e Fetch API supportano entrambi CORS, e può inviare sia la richiesta POST che GET

Ma ha i suoi limiti. Il server ha bisogno di rivendicare l’ Access-Control-Allow-Origin e non può essere impostato su ‘*’.

E se vuoi che qualsiasi origine possa inviarti una richiesta, devi JSONP (devi anche impostare Access-Control-Allow-Origin , ma può essere ‘*’)

Per un sacco di modalità di richiesta se non sai come scegliere, penso che tu abbia bisogno di un componente funzionale completo per farlo. Mi consente di introdurre un componente semplice https://github.com/Joker-Jelly/catta


Se utilizzi un browser moderno (> IE9, Chrome, FF, Edge, ecc.), Molto ti consiglia di utilizzare un componente semplice ma di bellezza https://github.com/Joker-Jelly/catta . Non ha alcuna dipendenza, meno di 3KB e supporta Fetch, AJAX e JSONP con la stessa syntax e opzioni dello stesso campione.

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

Supporta anche tutto il modo di importare nel tuo progetto, come il modulo ES6, CommonJS e persino in HTML.