Aller au menu - Aller au contenu

Icône L'XMLHttpRequest cross-domain

Mise à jour : 07/12/2010
Difficulté : Intermédiaire Intermédiaire
6 849 visites depuis 7 jours, dont 360 sur ce chapitre classé 33/786
Chapitre rédigé par Thunderseb
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Introduction

Avant de parler d'XMLHttpRequest cross-domain, il est nécessaire de définir ce qu'est le principe cross-domain.

Le cross-domain



Cross-domain signifie croisement de domaine. C'est un principe qui vise à faire communiquer deux domaines ensemble. Par exemple, monsite.com peut envoyer des données à tonsite.com, tout comme ce dernier peut renvoyer des données à monsite.com.

La plupart des techniques AJAX ne sont pas cross-domain pour des raisons évidentes de sécurité. Pour qu'une application cross-domain fonctionne, il faut que le domaine qui reçoit la requête soit autorisé à la traiter. C'est une mesure de sécurité obligatoire.

Image utilisateur


Il faut donc que le domaine à qui la requête est envoyée soit autorisé à répondre. Pour ce faire, on utilise l'Access Control, qui sera détaillé par la suite.

XMLHttpRequest et XDomainRequest



Faire communiquer deux scripts présents en des domaines différents est impossible avec XMLHttpRequest, dans sa spécification première.

Tous les navigateurs implémentent XMLHttpRequest dans sa spécification première (Level 1) qui ne permet pas de faire du cross-domain. Le W3C travaille sur la spécification 2 (Level 2) qui autorise le cross-domain.

Différences de point de vue



Pour résumer, pendant que le W3C travaille sur la deuxième spécification d'XMLHttpRequest, Microsoft implémente dans Internet Explorer 8 sa propre version du cross-domain, baptisée XDomainRequest. Microsoft justifie ce choix par le fait que la nouvelle version d'XMLHttpRequet ne le satisfait pas. La grosse différence entre XDomainRequest (XDR) et XHR est que ce n'est pas le même objet qui est utilisé, ce qui permet de ne pas s'embrouiller et de bien différencier les deux techniques.

Je vais donc vous parler des deux techniques bien qu'elles ne soient pas encore vraiment utilisables, car seul IE8 gère XDomainRequest et... aucun autre navigateur ne gère la version 2 d'XMLHttpRequest.

En réalité c'est faux, Firefox 3 gère la version 2 d'XHR, mais seulement dans les extensions, et non dans les pages Web. Le problème (parce que c'est bien un bug) est corrigé dans la version 3.1 Beta 1 !



On va commencer par voir comment instancier ce nouvel objet, pour nous verrons le fonctionnement d'Access Control.

XDomainRequest et XHR 2

XDomainRequest



XDomainRequest fonctionne grosso modo comme XMLHttpRequest, mais un peu plus simplement. Je ne vais pas rentrer dans les détails, c'est facile à comprendre :

Code : JavaScript
1
2
3
4
5
6
7
8
var xdr = new XDomainRequest(); 

xdr.onload = function() {
	alert(xdr.responseText);
}

xdr.open("GET", "http://www.foxycode.net/dev/ajax/XDomain_1.php");
xdr.send();


Ce qui change par rapport à XHR, c'est la propriété onload qui remplace et simplifie grandement onreadystatechange, readyState et status. Si onload est déclenché, c'est que tout est bon.

Pour info, cette propriété onload est ajoutée dans la spécification 2 d'XMLHttpRequest.


XMLHttpRequest 2



L'utilisation de l'objet XHR en cross-domain est exactement la même que celle que nous avons vue. L'objet a cependant été un peu simplifié en supportant l'évènement onload (comme XDR) et onloadstart.

Ainsi, on peut résumer un code XHR 2 comme ceci :

Code : JavaScript
1
2
3
4
5
6
7
8
var xdr = new XMLHttpRequest(); 

xdr.onload = function() {
	alert(xdr.responseText);
}

xdr.open("GET", "http://www.foxycode.net/dev/ajax/XDomain_1.php");
xdr.send();


C'est simplement le même code que pour en envoi XDomainRequest, il y a juste le nom de l'objet qui change.

Je rappelle que XHR 2 n'est pas encore géré par les différents navigateurs, il n'est donc pas possible de le tester pour le moment, excepté pour les développeurs d'extensions pour Firefox 3.


Combinaison des deux



Comme pour XHR, on va faire une fonction pour instancier facilement un objet XHR cross-domain. Je vais garder le nom de Microsoft pour nommer la fonction histoire de bien différencier les deux systèmes (ce qui fait que je suis plutôt en accord avec la dénomination fournie par Microsoft).

Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function getXDomainRequest() {
	var xdr = null;
	
	if (window.XDomainRequest) {
		xdr = new XDomainRequest(); 
	} else if (window.XMLHttpRequest) {
		xdr = new XMLHttpRequest(); 
	} else {
		alert("Votre navigateur ne gère pas l'AJAX cross-domain !");
	}
	
	return xdr;	
}


Cela s'utilise donc de cette façon :

Code : JavaScript
1
2
3
4
5
6
7
var xdr = getXDomainRequest();
xdr.onload = function() {
	alert(xdr.responseText);
}

xdr.open("GET", "http://www.foxycode.net/dev/ajax/XDomain_1.php");
xdr.send();


Tout cela, c'est pour instancier un objet cross-domain. Voyons maintenant comment autoriser le serveur à répondre à la requête.

L'Access Control

Pour savoir si le domaine questionné est autorisé à répondre il suffit simplement de lui indiquer par le biais d'un en-tête :

Code : PHP
1
<?php header("Access-Control-Allow-Origin: *"); ?>


L'en-tête Access-Control-Allow-Origin sert à définir le domaine pour lequel les données pourront être renvoyées. Dans mon exemple, l'astérisque signifie tous les domaines. Il est bien évidemment possible d'affiner cette sélection de domaines :

Code : PHP
1
2
3
4
5
<?php
header("Access-Control-Allow-Origin: *");              // Tous les domaines
header("Access-Control-Allow-Origin: monsite.com");    // Seul monsite.com peut y accéder
header("Access-Control-Allow-Origin: free.fr");  // Les sous-domaines de Free.fr sont autorisés, donc nayi.free.fr y a accès
?>


L'Access Control est en réalité beaucoup plus vaste que cela. Mais pour les besoins du tutoriel, il n'y a que Allow-Origin qui nous intéresse. Le reste est à découvrir par vous même, mais n'est pas géré complètement par les navigateurs.

Il existe aussi une version pour XML d'Access Control, mais non supportée par Internet Explorer.

Pour la petite histoire, Internet Explorer 8, en version beta 1 ne gérait pas l'Access Control, il fallait utiliser XDomainRequestAllowed: 1, qui ne faisait pas de différence entre les domaines (c'était juste 1 ou 0 comme valeurs). Mais dans l'optique de respecter un peu mieux les standards, la team de développement d'IE8 a décidé d'implémenter Access Control. XDomainRequestAllowed est déjà de l'histoire ancienne.

Exemple d'utilisation

Les données



Voici le fichier contenant les données. Il est hébergé sur www.foxycode.net et sera récupéré par le script sur nayi.free.fr :

Code : PHP
1
2
3
4
5
6
7
<?php 
header("Content-Type: text/plain");
header("Access-Control-Allow-Origin: *");
?>

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed hendrerit fringilla dui. 
Aenean malesuada, eros nec venenatis fringilla, ipsum mauris suscipit sem, nec semper velit dui nec felis.


L'appel



Le script ci-dessous se contente simplement d'aller questionner le fichier PHP hébergé sur foxycode.net :

Code : HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Techniques AJAX - XDomainRequest</title>
<script type="text/javascript">
<!-- 

function getXDomainRequest() {
        var xdr = null;
        
        if (window.XDomainRequest) {
                xdr = new XDomainRequest(); 
        } else if (window.XMLHttpRequest) {
                xdr = new XMLHttpRequest(); 
        } else {
                alert("Votre navigateur ne gère pas l'AJAX cross-domain !");
        }
        
        return xdr;        
}


function sendData() {
        var xdr = getXDomainRequest();
        xdr.onload = function() {
                alert(xdr.responseText);
        }
        
        xdr.open("GET", "http://www.foxycode.net/dev/ajax/XDomain_1.php");
        xdr.send();
}
 
//-->
</script>
</head>
<body>
<p>
        <input type="button" onclick="sendData();" value="Récupérer" />
</p>
</body>
</html>


Vous pouvez tester cet exemple à cette adresse avec la plupart des navigateurs récents comme Firefox 3.5, Internet Explorer 8, Google Chrome 3. Cela ne fonctionne pas dans Opera 10.5.

Notez toutefois que pour des raisons de sécurité, il n'est pas toujours possible de faire du cross-domain à partir d'un fichier local (un fichier sur votre PC) vers un fichier sur un serveur. C'est le cas d'Internet Explorer 8.
L'XMLHttpRequest cross-domain n'en est qu'à ses débuts. Il va falloir attendre un peu pour voir ce que ça va donner. La technologie peut cependant être pleinement utilisable avec Internet Explorer 8 donc peut servir pour des applications uniquement dédiées à Internet Explorer 8.

Quoi qu'il en soit, il faut attendre que les autres navigateurs commencent à implémenter cette nouvelle technologie. Mais la spécification d'XHR 2 n'étant pas terminée, il va falloir encore attendre un peu.
Chapitre précédent Sommaire Chapitre suivant

Partager

8 commentaires pour "L'XMLHttpRequest cross-domain"
Note moyenne : 3.60 / 4 (138 votes)
Pseudo Commentaire
Hors ligne Anonyme # Posté le 05/05/2009 à 08:40:42

Très intéressant ce concept de cross-domain mais concrètement, à quoi ça sert si on ne possède pas les deux sites ? Y a-t-il des sites qui fournissent leurs scripts via cette méthode ?
Sinon, XMLHttpRequest 2 est disponible depuis le 30 septembre 2008 à cette adresse ;)

Ça serait très sympa de faire un p'tit tuto dessus ou de mettre à jour le premier pour présenter les nouvelles fonctionnalités de cette deuxièmes version.

PS :
Citation : Thunderseb
La plupart plupart des techniques AJAX
Hors ligne don_yaska # Posté le 14/05/2009 à 18:17:31
Avatar

Études : UTC

@Captain Awesome: Pas nécessairement. Quand tu fais appel à une API (Google maps par exemple), tu as besoin d'envoyer des requètes sur un autre serveur, d'où le problème du cross-domain si tu utilises un objet XHR. :p

Très bon tuto :) Quelques suggestions pour cette partie cependant: peut-être faudrait-t-il proposer d'autres solutions que le XDR pour contourner le problème du cross-domain. Par exemple les proxys PHP (en utilisant l'extension cURL), ou bien les proxys Apache.

J'ai été confronté à ce problème et voici quelques liens qui peuvent servir (en anglais):
http://www.xml.com/pub/a/2005/11/09/fi [...] -harmful.html
http://www.simple-talk.com/dotnet/asp. [...] ices-in-ajax/
Hors ligne Dr.Tenma # Posté le 20/07/2009 à 11:04:11
Avatar

Bon tuto, mais ne répond pas à mes attentes.

don_yaska -> Merci beaucoup pour les liens que t'as fournis !
 
Hors ligne SoupeurStar # Posté le 14/09/2009 à 00:51:20
Avatar

avec XDomainRequest() IE8 peu pas utiliser responseXML, juste responseText....
(forcement ca aurait été trop facile sinon)
et ca c'est nul :(
 
Hors ligne wapper # Posté le 18/03/2010 à 23:59:15
Avatar

Bonjour,

Serait-il possible de mettre à jour ce tuto et, au passage, d'ajouter un exemple fonctionnel d'XDomainRequest() sous IE à partir d'une page locale, svp?

Par page locale, j'entends une page stockée n'importe où sur le poste client, pas dans localhost... ^^

Merci d'avance.

Si vous voulez qu'on puisse vous aider, veuillez indiquer votre code bancaire, en même temps que votre question, svp... ^^

 - Avancement de mon premier tuto: (70% sur 3 parties)
Comment créer une extension arbitraire, sous OpenSSL, svp?
 

Voir tous les commentaires