Ce blog a déménagé et parle maintenant uniquement anglais.

This blog has moved and now only speaks English.

blog.floriancargoet.com

See you there!

/home/florian

le blog de florian cargoet : du linux, du web et du logiciel libre



JSONP avec jQuery

19 February, 2009 (14:31) | jQuery, Webdev | Florian Cargoet

Catégorie Webdev : A propos du web, de son contenu, de ses outils...

Vous êtes certainement déjà au courant mais on ne peut pas faire d’appel Ajax sur un autre domaine que celui où tourne le script pour des raisons de sécurité. Si vous avez quand même besoin de récupérer des données cross-domain, il existe une technique : le JSONP (ou JSON with padding).
Un peu de théorie puis un cas pratique avec jQuery.

Le JSONP

Au lieu de récupérer du JSON, on va récupérer du JSONP, c’est-à-dire du JSON encapsulé dans un appel de fonction. Exemple :

?View Code JAVASCRIPT
//JSON
{x:1,y:3}
//JSONP
foo({x:1,y:3})

Les services web qui renvoient du JSON vous permettent en général de récupérer du JSONP en rajoutant le paramètre callback=foo dans l’url. Exemple :

Qu’est-ce qu’on en fait ?

Au lieu de faire un appel avec l’objet XHR classique, vous allez simplement rajouter une balise <script> dans votre code qui va charger le code distant (oui, charger des scripts d’un autre domaine est autorisé). Et la fonction foo() sera executé avec le JSON en paramètre. Il ne vous reste plus qu’à avoir une fonction foo() dans votre code pour traiter ces données.

Et jQuery dans tout ça ?

Plutot que de vous laisser créer une fontion nommée, d’ajouter son nom à l’url, d’insérer la balise script qui va bien, jQuery vous fait tout le boulot sans que vous vous en rendiez compte (ou presque) !

Un simple getJSON(url, data, callback) comme si vous étiez sur le même domaine. Il suffit d’indiquer =? dans l’url pour que jQuery détecte tout seul qu’il faut insérer ici un nom de callback (qu’il crée lui-même !).

?View Code JAVASCRIPT
$.getJSON('http://feeds.delicious.com/v2/json/popular?callback=?',function(data){
    //faites ce que vous voulez avec data !
    console.log(data);
});

Et Firebug répond : [Object, Object u=http://mashable.com/2009/02/18/how-to-guide/, Object, Object, Object, Object, Object, Object, Object, Object u=http://www.patorjk.com/software/taag/, Object, Object, Object u=http://www.crisisofcredit.com/, Object, Object]

Si vous voulez quelques alternatives avec jQuery en utilisant $.ajax() à la place de $.getJSON() :

?View Code JAVASCRIPT
//alternativement, vous pouvez préciser le type "jsonp"
$.ajax({
    url : 'http://feeds.delicious.com/v2/json/popular',
    dataType : 'jsonp',
    success : function(data){} //votre callback
});
 
//vous pouvez aussi préciser le paramètre à ajouter dans l'url
//(par défaut c'est callback)
$.ajax({
    url : 'http://api.flickr.com/services/feeds/photos_public.gne?tags=obama&amp;tagmode=any&amp;format=json',
    dataType : 'jsonp',
    jsonp : 'jsoncallback',
    success : function(data){} //votre callback
});

Et voilà le travail, on a récupéré du JSON en cross-domain sans se prendre la tête grâce à jQuery (ajouter callback=?, je ne trouve pas que ce soit très prise de tête ;-) . Et si c’est trop pour vous, utilisez $.ajax() avec le dataType jsonp ).

Cela va sans dire, il faut que le service que vous interrogez soit capable d’encapsuler le JSON dans un appel de fonction, sinon, ça ne fonctionnera pas.

Article précédent :
«

Commentaires

Commentaire de Julian Aubourg
le 18 March 2009, 10:21

J’ai eu quelques soucis avec $.getJSON et $.ajax lorsque le service ne répond pas ou qu’il impose des contraintes comme un nom de callback fixe. Du coup, j’ai fait un plugin spécifiquement adapté aux appels jsonp:
http://code.google.com/p/jquery-jsonp/

Commentaire de Florian Cargoet
le 18 March 2009, 12:29

Effectivement ça semble intéressant ! Je n’ai pas encore rencontré le problème des callbacks fixes, quels services fonctionnent comme ça ?
Je teste ton plugin dès que j’ai un peu de temps !

Commentaire de Julian Aubourg
le 20 March 2009, 8:52

C’est souvent un cumul avec une construction d’url ésotérique que la callback fixe devient nécessaire… avec tous les problèmes de collision que cela peut engendrer (et que $.jsonp gère).

Voir ici:
http://stackoverflow.com/questions/203194/using-a-named-function-as-the-callback-for-getjson-in-jquery-to-satisfy-faceboo

(surtout la deuxième réponse qui est, à mon avis, la plus pertinente).

Commentaire de Coincoin
le 11 November 2010, 13:07

Hello, merci pour l’article.
Je voulais surtout réagir sur ton captcha de commentaires, c’est tout de même très moisi comme antispam. Il suffit d’exécuter un bout de code tout con dans la console, t’as même jQuery c’est parfait. :D

var tmp = jQuery(‘#commentform .block-spam’).text().split(‘Combien font’);
jQuery(‘#commentform .block-spam input’).val(eval(tmp[1].replace(‘?’,”)));

Ciao.

Commentaire de Florian Cargoet
le 26 November 2010, 20:49

C’est un anti-bot. Pour le contourner, tu as du écrire un bout de code spécifique à mon site. Pour qu’un bot passe ce blocage, il faudrait que son concepteur prenne en compte mon site, ce qui est plus qu’improbable…
Pas un seul commentaire de la part d’un bot depuis la mise en place de ce plugin (et j’en avais pas mal avant) donc c’est plutôt satisfaisant.
Comme c’est un plugin WordPress, il est potentiellement répandu donc il peut être la cible d’une attaque spécifique (ca devient intéressant puisqu’on touche de nombreuses installations de WordPress d’un coup). Pour éviter ça, j’ai modifié le plugin pour demander une somme de 3 chiffres au lieu de 2 dans la version de base.

La preuve pour moi qu’il n’est absolument pas moisi est qu’il fonctionne à 100% depuis longtemps.

Commentaire de xalax
le 15 August 2011, 8:23

salut Florian,
Merci pour la clarté de tes explications!!!
dis-moi je suis peut-être complétement a coté de la plaque. Mais j’essaie d’appeler la fonction suivante (dans une page html contenant un div dont l’id est mondiv) de la façon suivante :

function myfunction() {
$.ajax({
url : ‘http://api.flickr.com/services/feeds/photos_public.gne?tags=obama&tagmode=any&format=json’,
dataType : ‘jsonp’,
jsonp : ‘jsoncallback’,
success : function(data){$(“mondiv”).append(data)} //votre callback
});
}

Mais il ne se passe rien. Naada. Pas d’erreur de script mais aucun résultat n’est affiché.
Quelqu’un a-t-il une idée de ce qui ne joue pas?

Commentaire de Florian Cargoet
le 15 August 2011, 23:21

Ce qui est passé à append doit être un “DOM element, HTML string, or jQuery object” d’après la doc. data n’est probablement pas de ce type. Ajoute un bon vieux console.log(data) dans ta callback pour vérifier que tu reçois bien les données, on ne sait jamais…

Commentaire de Tristan PERINET
le 16 February 2012, 12:16

J’ai implémenté ta solution mais il me met une erreur de syntax html à l’ouverture de la page et il arrête tout de suite l’exécution du code car je veux faire un alert(data) pour vérifier les données renvoyées mais rien n’est fait, est ce que tu as une solution ?

Il me met cette erreur :
syntax error sur cette ligne

Cordialement
Tristan PERINET MARQUET

Commentaire de Florian Cargoet
le 16 February 2012, 21:45

“syntax error sur cette ligne” ça n’aide pas beaucoup ! :-)
Points importants :
– cet article date de 2009, il faut sans doute adapter le code pour qu’il marche
– vérifie que ton code JS est valide (jslint/jshint ou IDE…)