javascript - utiliser - xmlhttprequest exemple




Comment envoyer une requête POST inter-domaines via JavaScript? (12)

Comment envoyer une requête POST inter-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.


  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.


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

  2. Créez un formulaire masqué, définissez sa méthode sur "post" avec target = votre premier iframe, et définissez optype 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 le javascript qui fera 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 ainsi que.

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.


CORS est pour vous. CORS est "Cross Origin Resource Sharing", est un moyen d'envoyer des requêtes interdomaines. Maintenant, les API XMLHttpRequest2 et Fetch supportent CORS, et peuvent envoyer des requêtes POST et GET

Mais il a ses limites. Le serveur a besoin de réclamer spécifiquement l' Access-Control-Allow-Origin , et il ne peut pas être mis à '*'.

Et si vous voulez que n'importe quelle origine puisse vous envoyer une requête, vous avez besoin de JSONP (vous devez également définir Access-Control-Allow-Origin , mais peut être '*')

Pour beaucoup de manière de demande si vous ne savez pas comment choisir, je pense que vous avez besoin d'un composant fonctionnel complet pour le faire. Laissez-moi présenter un composant simple https://github.com/Joker-Jelly/catta

Si vous utilisez un navigateur moderne (> IE9, Chrome, FF, Edge, etc.), Very vous recommande d'utiliser un composant simple mais beauté https://github.com/Joker-Jelly/catta .Il n'a pas de dépendance, Moins que 3 Ko, et il prend en charge Fetch, AJAX et JSONP avec la même syntaxe d'échantillon mortel et les options.

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

Il supporte aussi tout le chemin à importer vers votre projet, comme le module ES6, CommonJS et même <script> en HTML.


Devrait être possible avec une table personnalisée YQL + JS XHR, jetez un oeil à: http://developer.yahoo.com/yql/guide/index.html

Je l'utilise pour faire du côté client (js) html grattage, fonctionne bien (j'ai un lecteur audio complet, avec recherche sur internet / playlists / paroles / dernières informations fm, tous les clients js + YQL)




Niveau supérieur .... Vous devez avoir une configuration cname sur votre serveur afin que other-serve.your-server.com pointe vers other-server.com.

Votre page crée dynamiquement un iframe invisible, qui agit comme votre transport vers other-server.com. Vous devez ensuite communiquer via JS à partir de votre page vers le other-server.com et avoir des rappels qui retournent les données sur votre page.

Possible mais nécessite une coordination de your-server.com et other-server.com


Rester simple:

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

  2. ne devrait pas actualiser la page:
    Non, il ne rafraîchira pas la page car le success ou l' error 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
        }
    });

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 permettra pas d'envoyer des cookies dans la demande.)

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

  1. Créez un iframe avec un nom unique. (Les iframes utilisent un espace de nommage global pour l'ensemble du navigateur, donc choisissez 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 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 la même politique d'origine .

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

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.


Si vous voulez faire cela dans l'environnement ASP.net MVC avec JQuery AJAX, procédez comme suit: (ceci est un résumé de la solution proposée par this thread)

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") à laquelle nous publierons:

    [HttpPost]
    public JsonResult Save()
    {
        //Handle the post data...
    
        return Json(
            new
            {
                IsSuccess = true
            });
    }
    
  3. Ensuite, à partir de "caller.com", publiez les données d'un formulaire (avec l'ID 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
            }
        });
    


Mise à 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). Remarque: vous devez uniquement définir Access-Control-Allow-Origin pour les demandes NON OPTIONS . 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 pendant que vous continuez à 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. C'est un "reniflement" par le navigateur pour voir si le serveur est cool avec vous POSTing. Le serveur répond avec un "Access-Control-Allow-Origin" indiquant au navigateur son OK à POST | GET | ORIGIN si la requête provient de " http://from.com " ou " https://from.com ". Puisque le serveur est OK avec, le navigateur fera une 2ème demande (cette fois un POST). Il est recommandé que votre client définisse le type de contenu qu'il envoie. Vous devrez donc l'autoriser également.

MDN a un excellent article sur le contrôle d'accès HTTP , qui explique en détails comment fonctionne l'ensemble du flux. Selon leurs docs, il devrait "fonctionner dans les navigateurs prenant en charge XMLHttpRequest intersite". Ceci est un peu trompeur cependant, car je pense que seuls les navigateurs modernes permettent le POST inter-domaine. J'ai seulement vérifié cela fonctionne avec safari, chrome, FF 3.6.

Gardez à l'esprit les points suivants si vous faites ceci:

  1. Votre serveur devra gérer 2 requêtes par opération
  2. Vous devrez penser aux implications de sécurité. Soyez prudent avant de faire quelque chose comme 'Access-Control-Allow-Origin: *'
  3. Cela ne fonctionnera pas sur les navigateurs mobiles. Dans mon expérience, ils ne permettent pas du tout POST inter-domaine. 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. C'est une énorme douleur dans le cul, puisque vous ne pouvez pas utiliser de bonnes pratiques REST. Voir bug here (il est classé sous jQuery, mais je suppose que c'est un bug FF - semble être corrigé dans FF4).
  5. Renvoyez toujours les en-têtes ci-dessus, pas seulement sur les requêtes OPTION. FF en a besoin dans la réponse du POST.




cross-domain