web-dev-qa-db-fra.com

AJAX appel entre domaines

Je connais la stratégie AJAX entre domaines . Je ne peux donc pas appeler " http://www.google.com " via une requête HTTP ajax et afficher Les résultats. quelque part sur mon site.

Je l'ai essayé avec dataType "jsonp", cela fonctionnerait, mais j'obtiens une erreur de syntaxe (évidemment parce que les données reçues ne sont pas au format JSON)

Existe-t-il une autre possibilité de recevoir/afficher des données d'un domaine étranger? Les iFrames suivent la même politique.

64
jAndy

Le seul moyen (facile) d'obtenir des données inter-domaines à l'aide de AJAX consiste à utiliser un langage côté serveur comme proxy comme Andy E . Voici un petit exemple pour implémenter cela en utilisant jQuery:

La partie jQuery:

$.ajax({
    url: 'proxy.php',
    type: 'POST',
    data: {
        address: 'http://www.google.com'
    },
    success: function(response) {
        // response now contains full HTML of google.com
    }
});

Et le PHP (proxy.php):

echo file_get_contents($_POST['address']);

Aussi simple que cela. Sachez simplement ce que vous pouvez ou ne pouvez pas faire avec les données récupérées.

65
Tatu Ulmanen

Vous devrez insérer dynamiquement une balise de script dans la page qui référence les données. En utilisant JSONP, vous pouvez exécuter une fonction de rappel lorsque le script a été chargé.

La page wikipedia sur JSONP présente un exemple concis. la balise script:

<script type="text/javascript" src="http://domain1.com/getjson?jsonp=parseResponse">
</script>

renverrait les données JSON encapsulées dans un appel à parseResponse:

parseResponse({"Name": "Cheeso", "Rank": 7})

(en fonction de la configuration du script getjson sur domain1.com)

Le code pour insérer la balise dynamiquement serait quelque chose comme:

var s = document.createElement("script");
s.src = "http://domain1.com/getjson?jsonp=parseResponse";
s.type = "text/javascript";
document.appendChild(s);
18
alunny

Vous pouvez utiliser YQL pour faire la demande sans avoir à héberger votre propre proxy. J'ai créé une fonction simple pour faciliter l'exécution des commandes:

function RunYQL(command, callback){
     callback_name = "__YQL_callback_"+(new Date()).getTime();
     window[callback_name] = callback;
     a = document.createElement('script');
     a.src = "http://query.yahooapis.com/v1/public/yql?q="
             +escape(command)+"&format=json&callback="+callback_name;
     a.type = "text/javascript";
     document.getElementsByTagName("head")[0].appendChild(a);
}

Si vous avez jQuery, vous pouvez utiliser $ .getJSON à la place.

Un échantillon peut être ceci:

RunYQL('select * from html where url="http://www.google.com/"',
       function(data){/* actions */}
);
16
Alexandre Vicente

Malheureusement (ou heureusement) pas. La politique inter-domaines existe pour une raison. Si elle était facile à contourner, elle ne serait pas très efficace comme mesure de sécurité. Autre que JSONP, la seule option est de proxy les pages en utilisant votre propre serveur .

Avec un iframe, ils sont soumis à la même politique. Bien sûr, vous pouvez afficher les données d'un domaine externe, vous ne pouvez simplement pas les manipuler.

11
Andy E

J'utilise ce code pour l'appel ajax entre domaines, j'espère que cela en aidera plus d'un ici. J'utilise la bibliothèque de prototypes et vous pouvez faire la même chose avec JQuery ou Dojo ou n'importe quoi d'autre:

Étape 1: créez un nouveau fichier js et mettez cette classe à l'intérieur, je l'ai appelé xss_ajax.js

var WSAjax = Class.create ({
    initialize: function (_url, _callback){
        this.url = _url ;
        this.callback = _callback ;
        this.connect () ;
    },
    connect: function (){
        var script_id = null;
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('src', this.url);
        script.setAttribute('id', 'xss_ajax_script');

        script_id = document.getElementById('xss_ajax_script');
        if(script_id){
            document.getElementsByTagName('head')[0].removeChild(script_id);
        }

        // Insert <script> into DOM
        document.getElementsByTagName('head')[0].appendChild(script);
    },
    process: function (data){
        this.callback(data) ;
    }

}) ;

Cette classe crée un élément de script dynamique qui attribue les attributs src à votre fournisseur de données JSON (JSON-P en fait, car votre serveur distant doit fournir les données dans le format suivant: call_back_function (// json_data_here) :: :: JSON sera directement évalué en tant que fonction (nous allons parler de la transmission du nom de la méthode de rappel au serveur à l'étape 2), le concept principal étant que les scripts comme les éléments img ne sont pas concernés par les contraintes SOP.

Étape 2: dans toute page HTML où vous souhaitez extraire le JSON de manière asynchrone (nous appelons cela AJAJ ~ JAvascript asynchrone + JSON :-) au lieu de AJAX qui utilise l'objet XHTTPRequest), procédez comme suit

//load Prototype first
//load the file you've created in step1


var xss_crawler = new WSAjax (
     "http://your_json_data_provider_url?callback=xss_crawler.process"
 ,   function (_data){
            // your json data is _data and do whatever you like with it 
        }) ;

Rappelez-vous le rappel à l'étape 1? nous le transmettons au serveur et celui-ci renverra le JSON incorporé à cette méthode. Ainsi, dans notre cas, le serveur renverra un code javascript évalable, xss_crawler.process (// the_json_data). N'oubliez pas que xss_crawler est une instance de la classe WSAjax. Le code du serveur dépend de vous (si c'est le vôtre), mais la plupart des fournisseurs de données Ajax vous permettent de spécifier la méthode de rappel dans les paramètres, comme nous l'avons fait . Dans Ruby on Rails, je viens de le faire

render :json=>MyModel.all(:limit=>10), :callback => params[:callback],:content_type => "application/json"

et c'est tout, vous pouvez maintenant extraire des données d'un autre domaine à partir de vos applications (widgets, cartes, etc.), au format JSON uniquement, n'oubliez pas.

J'espère que cela a été utile, merci de votre patience :-), paix et désolé pour le formatage du code, cela ne fonctionne pas bien

4
R Francky

après quelques recherches, la seule "solution" à ce problème est d'appeler:

if($.browser.mozilla)
   netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');

cela demandera à un utilisateur s'il permet à un site Web de continuer. Après confirmation, tous les appels Ajax, quel que soit leur type de données, seront exécutés.

Cela fonctionne pour les navigateurs mozilla. Dans IE <8, un utilisateur doit autoriser un appel interdomaine.

chrome/safari: Je n'ai pas trouvé d'indicateur de configuration pour ces navigateurs jusqu'à présent.

utiliser JSONP comme type de données serait agréable, mais dans mon cas, je ne sais pas si un domaine est nécessaireaccès prend en charge les données dans ce format.

Une autre solution consiste à utiliser HTML5 postMessage, qui fonctionne également entre les domaines, mais je ne peux pas me permettre de condamner mes utilisateurs à des navigateurs HTML5.

4
jAndy

Si vous utilisez un script php pour obtenir la réponse du serveur distant, ajoutez cette ligne au début:

header("Access-Control-Allow-Origin: *");
3
akadi81

JSONP est la meilleure option, à mon avis. Essayez de comprendre pourquoi vous obtenez l'erreur de syntaxe - êtes-vous sûr que les données reçues ne sont pas JSON? Alors peut-être que vous utilisez l’API de façon erronée.

Une autre façon de l'utiliser, mais je ne pense pas que cela s'applique dans votre cas, est d'avoir un iFrame dans la page qui src se trouve dans le domaine que vous souhaitez appeler. Demandez-lui de faire les appels pour vous, puis utilisez JS pour communiquer entre iFrame et la page. Cela contournera le domaine croisé, mais uniquement si vous pouvez avoir le src de iFrame dans le domaine que vous souhaitez appeler.

2
Nir

Voici un moyen facile de le faire, sans avoir à utiliser quoi que ce soit, ni même JSON.

Commencez par créer un script côté serveur pour traiter vos demandes. Quelque chose comme http://www.example.com/path/handler.php

Vous l'appelerez avec des paramètres, comme ceci: .../handler.php? Param1 = 12345 & param2 = 67890

À l’intérieur de celui-ci, après le traitement des données reçues, output:

document.serverResponse('..all the data, in any format that suits you..');
// Any code could be used instead, because you dont have to encode this data
// All your output will simply be executed as normal javascript

Maintenant, dans le script côté client, utilisez ce qui suit:

document.serverResponse = function(param){ console.log(param) }

var script = document.createElement('script');
script.src='http://www.example.com/path/handler.php?param1=12345&param2=67890';
document.head.appendChild(script);

La seule limite de cette approche est la longueur maximale des paramètres que vous pouvez envoyer au serveur. Mais, vous pouvez toujours envoyer plusieurs demandes.

1
AlexTR

Vous pouvez utiliser la technologie CORS pour configurer les deux serveurs (le serveur sur lequel Javascript est exécuté et le serveur API externe).

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

p.s .: la réponse https://stackoverflow.com/a/37384641/6505594 suggère également cette approche et ouvre le serveur d'API externe à tout le monde.

0
morhook