Question Comment envoyer une demande POST entre domaines via JavaScript?


Comment envoyer une demande POST entre domaines via JavaScript?

Notes - il ne devrait pas actualiser la page, et j'ai besoin de saisir et d'analyser la réponse par la suite.

Votre aide avec quelques exemples de code sera très appréciée.


511
2017-11-18 13:43


origine


Réponses:


Mettre à jour: Avant de continuer tout le monde devrait lire et comprendre le tutoriel html5rocks sur CORS. C'est facile à comprendre et très clair.

Si vous contrôlez le serveur en cours de POST, utilisez simplement la «norme de partage de ressources d'origine croisée» en définissant des en-têtes de réponse sur le serveur. Cette réponse est discutée dans d'autres réponses dans ce fil, mais pas très clairement à mon avis.

En bref, voici comment vous pouvez accomplir le POST interdomaine de from.com/1.html à to.com/postHere.php (en utilisant PHP comme exemple). Note: il vous suffit de définir Access-Control-Allow-Origin pour NON OPTIONS requests - cet exemple définit toujours tous les en-têtes pour un extrait de code plus petit.

  1. Dans postHere.php, configurez les éléments suivants:

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

    Cela permet à votre script de faire du POST, du GET et des OPTIONS entre domaines. Cela deviendra clair lorsque vous continuerez à lire ...

  2. Configurez votre POST interdomaine depuis JS (exemple 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.');
        }
    });
    

Lorsque vous effectuez le POST à ​​l'étape 2, votre navigateur envoie une méthode "OPTIONS" au serveur. Ceci est un "sniff" par le navigateur pour voir si le serveur est cool avec vous POST. Le serveur répond avec un "Access-Control-Allow-Origin" indiquant au navigateur qu'il est OK à POST | GET | ORIGIN si la requête provient de "http://from.com" ou "https://from.comComme le serveur est OK, le navigateur fera une deuxième requête (cette fois-ci un POST) .C'est une bonne habitude de demander à votre client de définir le type de contenu qu'il envoie - donc vous devrez le faire aussi .

MDN a un excellent article sur Contrôle d'accès HTTP, cela va dans le détail de la façon dont le flux entier fonctionne. Selon leurs docs, il devrait "fonctionner dans les navigateurs prenant en charge XMLHttpRequest intersite". C'est un peu trompeur cependant, car je PENSE seuls les navigateurs modernes autorisent le POST interdomaine. J'ai seulement vérifié cela fonctionne avec safari, chrome, FF 3.6.

Gardez à l'esprit ce qui suit si vous faites ceci:

  1. Votre serveur devra gérer 2 requêtes par opération
  2. Vous devrez réfléchir aux implications en matière de sécurité. Soyez prudent avant de faire quelque chose comme 'Access-Control-Allow-Origin: *'
  3. Cela ne fonctionnera pas sur les navigateurs mobiles. D'après mon expérience, ils n'autorisent pas le POST interdomaine. J'ai testé Android, iPad, iPhone
  4. Il y a un gros bug dans FF <3.6 où si le serveur retourne un code de réponse non 400 ET qu'il y a un corps de réponse (erreurs de validation par exemple), FF 3.6 n'obtiendra pas le corps de la réponse. Ceci est une énorme douleur dans le cul, puisque vous ne pouvez pas utiliser de bonnes pratiques REST. Voir bug ici (son classé sous jQuery, mais je suppose que c'est un bug FF - semble être corrigé dans FF4).
  5. Retournez toujours les en-têtes ci-dessus, pas seulement sur les requêtes OPTION. FF en a besoin dans la réponse du POST.

362
2017-09-30 01:34



Si vous contrôlez le serveur distant, vous devriez probablement utiliser CORS, comme décrit dans cette réponse; Il est pris en charge dans IE8 et les versions récentes de FF, GC et Safari. (Mais dans IE8 et 9, CORS ne vous autorisera pas à envoyer des cookies dans la requête.)

Donc, si vous ne pas contrôler le serveur distant, ou si vous devez prendre en charge IE7, ou si vous avez besoin de cookies et que vous devez prendre en charge IE8 / 9, vous voudrez probablement utiliser une technique iframe.

  1. Créez un iframe avec un nom unique. (Les iframes utilisent un espace de noms global pour le navigateur entier, choisissez donc un nom qu'aucun autre site Web n'utilisera.)
  2. Construire un formulaire avec des entrées cachées, en ciblant l'iframe.
  3. Soumettez le formulaire.

Voici un exemple de code; Je l'ai testé sur 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();
}

Il faut se méfier! Vous ne pourrez pas lire directement la réponse du test POST, car l'iframe existe sur un domaine distinct. Les cadres ne sont pas autorisés à communiquer entre eux à partir de différents domaines; c'est le politique de même origine.

Si vous contrôlez le serveur distant mais que vous ne pouvez pas utiliser CORS (par exemple parce que vous êtes sur IE8 / IE9 et que vous devez utiliser des cookies), il existe des moyens de contourner la stratégie de même origine, par exemple en utilisant window.postMessage et / ou l'une des bibliothèques vous permettant d'envoyer des messages inter-domaines dans des navigateurs plus anciens:

Si vous ne contrôlez pas le serveur distant, vous ne pouvez pas lire la réponse du POST, point. Cela causerait des problèmes de sécurité autrement.


118
2018-05-29 18:50



  1. Créer un iFrame,
  2. mettre un formulaire dedans avec des entrées cachées,
  3. définir l'action du formulaire sur l'URL,
  4. Ajouter iframe au document
  5. soumettre le formulaire

Pseudocode

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

Vous voulez probablement styliser l'iframe, être caché et absolument positionné. Je ne suis pas sûr que l'affichage intersite sera autorisé par le navigateur, mais si c'est le cas, voici comment le faire.


47
2017-11-18 13:49



Rester simple:

  1. POST inter-domaines:
    utilisation crossDomain: true,

  2. ne doit pas rafraîchir la page: 
    Non, il ne rafraîchira pas la page en tant que success ou error Le rappel asynchrone sera appelé lorsque le serveur renvoie la réponse.


Exemple de script:

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

17
2017-10-03 17:01



Si vous avez accès à tous les serveurs concernés, insérez ce qui suit dans l'en-tête de la réponse pour la page demandée dans l'autre domaine:

PHP:

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

Par exemple, dans le code xmlrpc.php de Drupal, vous feriez ceci:

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

Cela crée probablement un problème de sécurité et vous devez vous assurer de prendre les mesures appropriées pour vérifier la demande.


16
2018-01-22 00:40



Vérifier la post_method fonctionner dans http://taiyolab.com/mbtweet/scripts/twitterapi_call.js - un bon exemple pour la méthode iframe décrite ci-dessus.


9
2018-02-24 22:03



  1. Créez deux iframes cachés (ajoutez "display: none;" au style css). Faites que votre deuxième iframe pointe sur quelque chose de votre propre domaine.

  2. Créez un formulaire masqué, définissez sa méthode pour "publier" avec target = votre premier iframe, et éventuellement définissez enctype sur "multipart / form-data" (je pense que vous voulez faire un POST car vous voulez envoyer des données en plusieurs parties comme des images) ?)

  3. Lorsque vous êtes prêt, faites le formulaire submit () le POST.

  4. Si vous pouvez obtenir l'autre domaine pour retourner javascript qui fera de la communication inter-domaines avec Iframes (http://softwareas.com/cross-domain-communication-with-iframes) alors vous avez de la chance, et vous pouvez capturer la réponse aussi bien.

Bien sûr, si vous voulez utiliser votre serveur comme proxy, vous pouvez éviter tout cela. Il suffit de soumettre le formulaire à votre propre serveur, qui transmettra la requête à l'autre serveur (en supposant que l'autre serveur n'est pas configuré pour remarquer les différences IP), obtiendra la réponse et retournera ce que vous voulez.


6
2018-03-09 15:13



Une autre chose importante à noter !!! Dans Exemple ci-dessus, il est décrit comment utiliser

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

JQuery 1.6 et inférieur a un bogue avec XHR inter-domaine. Selon Firebug, aucune requête, à l'exception des OPTIONS, n'a été envoyée. Pas d'article. Du tout.

J'ai passé 5 heures à tester / régler mon code. Ajout d'un grand nombre d'en-têtes sur le serveur distant (script) Sans aucun effet. Mais plus tard, j'ai mis à jour JQuery lib à 1.6.4, et tout fonctionne comme un charme.


6
2018-01-25 17:13



Si vous souhaitez effectuer cela dans l'environnement ASP.net MVC avec JQuery AJAX, procédez comme suit: (Ceci est un résumé de la solution proposée à ce fil)

Supposons que "caller.com" (peut être n'importe quel site Web) doit publier sur "server.com" (une application ASP.net MVC)

  1. Sur Web.config de l'application "server.com", ajoutez la section suivante:

      <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>
    
  2. Sur le "server.com", nous aurons l’action suivante sur le contrôleur (appelé "Home") sur lequel nous publierons:

    [HttpPost]
    public JsonResult Save()
    {
        //Handle the post data...
    
        return Json(
            new
            {
                IsSuccess = true
            });
    }
    
  3. Ensuite, depuis "caller.com", postez les données d'un formulaire (avec l'identifiant HTML "formId") sur "server.com" comme suit:

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

5
2018-05-06 17:32