<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Border-Labs &#187; JSON</title>
	<atom:link href="http://border-labs.fr/?cat=5&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://border-labs.fr</link>
	<description>... souvent à la limite</description>
	<lastBuildDate>Fri, 04 Mar 2011 16:36:17 +0000</lastBuildDate>
	<language>fr-FR</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.8.41</generator>
	<item>
		<title>JSON-P</title>
		<link>http://border-labs.fr/?p=21</link>
		<comments>http://border-labs.fr/?p=21#comments</comments>
		<pubDate>Fri, 07 Jan 2011 15:35:17 +0000</pubDate>
		<dc:creator><![CDATA[BlackAdder]]></dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[CORS]]></category>
		<category><![CDATA[JSON-P]]></category>
		<category><![CDATA[JSONP]]></category>
		<category><![CDATA[onError]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[XHR]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[XMLHttpRequest]]></category>

		<guid isPermaLink="false">http://border-labs.fr/WordPress/?p=21</guid>
		<description><![CDATA[JSON-P est une utilisation particulière de JSON. Lorsqu&#8217;on fait un appel ajax via une XHR (XMLHttpRequest), on est soumis à la règle de sécurité dite du &#171;&#160;same origin policy&#160;&#187; qui précise qu&#8217;une page dans le navigateur n&#8217;accepte des requètes XHR que &#8230; <a href="http://border-labs.fr/?p=21">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>JSON-P est une utilisation particulière de JSON.</p>
<p>Lorsqu&rsquo;on fait un appel ajax via une <abbr id="XHR" title="XML HTTP Request" lang="en">XHR </abbr>(XMLHttpRequest), on est soumis à la règle de sécurité dite du &laquo;&nbsp;same origin policy&nbsp;&raquo; qui précise qu&rsquo;une page dans le navigateur n&rsquo;accepte des requètes XHR que si elles interrogent des serveurs situés dans ce domaine.</p>
<p>Ceci commence à changer sur les navigateurs récents avec le <abbr id="CORS" title="Cross Origin Resource Sharing" lang="en">CORS</abbr>(<a title="W3C Cross Origin Resources Sharing" href="http://www.w3.org/TR/cors/" target="_blank">cross-origin resource sharing</a>, norme W3C dont le support ne s&rsquo;est pas encore généralisé).</p>
<p>Cette restriction du &laquo;&nbsp;same origin policy&nbsp;&raquo; ne s&rsquo;appliquent pas sur la balise<code>SCRIPT</code>. Une page HTML peut en effet comporter des balises <code>SCRIPT</code>téléchargeant des fichiers sources provenant de n&rsquo;importe quel domaine.</p>
<p>L&rsquo;idée est donc d&rsquo;utiliser des balises <code>SCRIPT</code> pour télécharger du JSON de façon à s&rsquo;affranchir de la contrainte du &laquo;&nbsp;same origin policy&nbsp;&raquo;. Néanmoins, charger du JSON de cette façon ne fonctionne pas directement. En effet, un fragment tel que</p>
<p><code>&lt;SCRIPT SRC="www.mondomaine.com/getJSON"&gt;&lt;/SCRIPT&gt;</code></p>
<p>téléchargera effectivement le flux JSON rendu par le serveur,  mais n&rsquo;en fera rien ; il ne sera ni mémorisé dans une variable javascript, ni utilisable par une fonction javascript.</p>
<p>C&rsquo;est ainsi qu&rsquo;est né, en 2005, l&rsquo;idée du JSON-P ou JSON Padding, il s&rsquo;agit de demander au serveur d&rsquo;encapsuler sa réponse JSON dans un appel de fonction, fonction qui est précisée dans l&rsquo;url d&rsquo;appel (cette fonction joue le rôle de callback), . Cela pourra donner par exemple (si le serveur utilise l&rsquo;attribut jsonp_callback pour préciser le callback) :<br />
<code>&lt;SCRIPT SRC="www.mondomaine.com/getJSONP?jsonp_callback=maFonction"&gt;&lt;/SCRIPT&gt;</code><br />
Lors de l&rsquo;appel de l&rsquo;url précédente, le serveur générera alors le code javascript suivant :</p>
<pre><code>maFonction({ .. le code JSON proprement dit })</code></pre>
<p>qui sera appelé lorsque la balise aura terminé le téléchargement de ce code. La fonction <code>maFonction </code>aura un unique argument qui est le code JSON ramené</p>
<p><code>function maFonction(jsonData){<br />
...<br />
}<br />
</code></p>
<p>Avantages</p>
<p>Un avantage de cette approche c&rsquo;est que chaque client du serveur peut préciser sa propre fonction et donc utiliser le code du serveur de la façon qu&rsquo;il souhaite : le serveur ne choisit pas comment il encapsule le code JSON, c&rsquo;est bien la page dans le navigateur qui précise la fonction qu&rsquo;il faudra appeler.</p>
<p>Un second avantage est qu&rsquo;il est possible d&rsquo;utiliser une politique de cache sur l&rsquo;url en question (le fragment JSONP pouvant être conservé dans le cache du navigateur).<br />
Un autre avantage est lié au nombre de connexions simultanées qu&rsquo;autorise le serveur. Les navigateurs actuels limitent le nombre de connexions simultanées sur le même domaine. Cette contrainte s&rsquo;applique donc sur les appels XHR qui sont bloqués tant qu&rsquo;ils restent d&rsquo;autres requêtes sur le même domaine.</p>
<p>Cette contrainte ne s&rsquo;applique pas sur la balise <code>SCRIPT </code>: les appels JSONP peuvent donc avoir lieu simultanément à partir du moment où ils appellent des <code>hosts </code>différents.</p>
<h3>Inconvénients</h3>
<h4>Problèmes liés à la sécurité</h4>
<p>JSON-P pose de sérieux problèmes de sécurité liées au attaques du type <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">cross-site request forgery</a>. Par exemple, une page malveillante peut récupérer des données JSON appartenant à un autre domaine, ces données (par exemple des données privées de l&rsquo;utilisateur logué sur l&rsquo;autre domaine) sont alors évaluées dans le contexte de la page malveillante.</p>
<p>Pour éviter ce genre de problème, il faut que le serveur ne fasse pas de réponse quand il détecte que la requête d&rsquo;appel n&rsquo;est pas valide, par exemple en effectuant une vérification du referrer de la request ou en effectuant une vérification syntaxique du callback utilisé.</p>
<p>Un autre problème, lié à l&rsquo;injection javascript est qu&rsquo;un serveur malveillant introduise dans sa réponse du code javascript permettant de récupérer des informations personnelles de l&rsquo;utilisateur du navigateur. Il existe plusieurs tentatives pour éviter ce problème. Par exemple on pourrait introduire au niveau du navigateur un parser spécifique qui vérifierait la syntaxe de la réponse JSON-P, potentiellement en spécifiant un type <code>mime </code>spécifique à la balise <code>SCRIPT</code>. (cf. <a href="http://www.json-p.org/">http://www.json-p.org/</a>).</p>
<p>Gestion d&rsquo;erreur</p>
<p>La gestion d&rsquo;erreur avec JSONP, dans le cas où la requête n&rsquo;arrive pas, est plus complexe que pour les appels XHR. Il existe à cet effet les événements<code>onerror</code>, mais ils ne sont pas supportés par tous les navigateurs (en fait, la plupart des navigateurs supporte l&rsquo;événement <code>onerror </code>sur la <code>window</code>, mais sous IE, l&rsquo;événement <code>onerror </code>sur la window n&rsquo;est déclenché que sur une erreur javascript, pas sur une erreur de chargement).</p>
<p>Optimisations</p>
<p>En effet, l&rsquo;utilisation la plus courante de JSONP se fait via l&rsquo;insertion dynamique de balises <code>SCRIPT</code>. Ainsi, plutôt que de créer dynamiquement une XHR, on insère une balise <code>SCRIPT </code>avec une url JSON-P. Dans ce type d&rsquo;utilisation de JSON-P, Google, dans son implantation de <a title="Instant preview" href="http://googlecode.blogspot.com/2010/11/instant-previews-under-hood.html">Google Instant Preview</a> précise deux conseils intéressants :</p>
<ul>
<li>Si on insère la balise <code>SCRIPT </code>directement (via<code>document.createElement</code>), certains navigateurs afficheront que la page est encore en cours de chargement même si toutes les requêtes sont terminées. Pour éviter ce problème, il faut encapsuler la création de la balise dans un <code>window.setTimeout</code>.</li>
<li>Une fois que l&rsquo;appel est terminé et la fonction de callback appelée, il est préférable de mettre à <code>null </code>l&rsquo;attribut <code>SRC</code> de la balise <code>SCRIPT </code>et de retirer la balise. Sur certains navigateurs, l&rsquo;accumulation de balises<code>SCRIPT</code>semble ralentir l&rsquo;exécution au fur et à mesure.</li>
</ul>
<h3>Exemple</h3>
<p>Un programme minimum en PHP pourrait être :</p>
<div id="_mcePaste">
<div id="_mcePaste">&lt;?php</div>
<div id="_mcePaste">data = &laquo;&nbsp;{ name: \&nbsp;&raquo;kate\&nbsp;&raquo; }&nbsp;&raquo;;</div>
<div id="_mcePaste">echo $_GET['jsonp_callback'] . &lsquo;(&lsquo; . $data . &lsquo;);&rsquo;;</div>
<div id="_mcePaste">?&gt;</div>
</div>
<p>où <code>jsonp_callback est </code>le paramètre de la requête qui contient le nom de la méthode à appeler.</p>
<p>On peut par exemple appeler le serveur dans une page HTML contenant :</p>
<p><code>&lt;SCRIPT SRC="http://localhost/json_sample1.php?jsonp_callback =aler<a href="http://localhost/json_sample1.php?json=%22%7B%5C%22claude%5C%22%20:%20%5C%22delaye%5C%22%7D%22&amp;jsonp=alert">t</a>"&gt;&lt;/SCRIPT&gt;</code></p>
<p>évidemment, on utilisera plutôt une création dynamique de la balise <code>SCRIPT</code>, par exemple via un fragment javascript tel que :</p>
<p><code>var url="http://localhost/json_sample1.php?param=12";<br />
url+="&amp;jsonp_callback=myCallback";</code></p>
<p><code>// Création dynamique d'un tag SCRIPT avec la bonne url<br />
var tagScript=document.createElement("SCRIPT");<br />
tagScript.src=url;<br />
var cible=document.getElementById("monAppel");<br />
cible.appendChild(tagScript);<br />
</code></p>
<p>Les fichiers de test correspondants sont disponibles dans cette <a title="fichiers d'exemple JSON-P" href="http://localhost/essaiJSONP.zip">archive</a>.</p>
<div id="_mcePaste">&lt;?php</div>
<div id="_mcePaste">data = &laquo;&nbsp;{ name: \&nbsp;&raquo;kate\&nbsp;&raquo; }&nbsp;&raquo;;</div>
<div id="_mcePaste">echo $_GET['jsonp_callback'] . &lsquo;(&lsquo; . $data . &lsquo;);&rsquo;;</div>
<div id="_mcePaste">?&gt;</div>
<p>&lt;?phpdata = &laquo;&nbsp;{ name: \&nbsp;&raquo;kate\&nbsp;&raquo; }&nbsp;&raquo;;echo $_GET['jsonp_callback'] . &lsquo;(&lsquo; . $data . &lsquo;);&rsquo;;?&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://border-labs.fr/?feed=rss2&#038;p=21</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
