Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    janvier 2008
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2008
    Messages : 253
    Points : 84
    Points
    84

    Par défaut Ajax cross-domain qui ne fonctionne pas

    Bonjour à tous,

    Je fais face à un problème qui vraisemblablement relève de la manière dont jQuery 1.6.1 fait les requêtes cross-domain.
    Mon site propose plusieurs sous-domaines dont un qui contient toutes les ressources communes (images, css, js) aux autres. J'ai donc besoin de charger régulièrement des fichiers de configuration par exemple stocké sur ce dernier (qu'on appellera racine.exemple.com dans notre cas).

    Lorsque je demande le chargement d'un de ces fichiers de configuration qui se présente sous la forme d'un fichier ini, j'obtiens différents messages suivant le navigateur employé. Voici tout d'abord mon code :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    $.ajax({
    	async:false,
    	crossDomain:true,
    	url:url,
    	method:"GET",
    	succss:function (data){
    		file_details.content = data;
    	},
    	error:function (xhr, status, error){
    		alert("Erreur de chargement du fichier '"+url+"' : "+xhr.responseText+" ("+status+" - "+error+")");
    	},
    	dataType:'text'
    });
    Ici, url contient donc l'adresse vers un fichier du type racine.exemple.com/config.ini et on se contente de placer le contenu texte du fichier dans file_details.content en cas de succès.
    En cas d'erreur, on affiche les détails du probleme :

    - Sous IE9 j'obtiens ce message :
    Erreur de chargement du fichier 'http://racine.exemple.com/config.ini' : undefined (erreur - Erreur : Accès refusé).
    - Alors que sous FF4 :
    Erreur de chargement du fichier 'http://racine.exemple.com/config.ini' : undefined (error - [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE)" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: http://code.jquery.com/jquery-1.6.1.min.js :: <TOP_LEVEL> :: line 27" data: no])
    Je ne comprends pas bien. J'ai également d'y insérer le code qui exploite la méthode YQL mais ca produit le même effet sans différences dans les messages ni les codes d'erreur.

    Je précise que la requête se fait en synchrone car j'attends d'avoir chargé toute ma config côté client pour poursuivre. Je souhaite garder le format ini.

    Est-ce que quelqu'un aurait une explication?
    Merci par avance, bon week end.

  2. #2
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    juin 2008
    Messages
    23 648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2008
    Messages : 23 648
    Points : 91 557
    Points
    91 557
    Billets dans le blog
    20

    Par défaut

    qui vraisemblablement relève de la manière dont jQuery 1.6.1 fait les requêtes cross-domain.
    Ben ça relève surtout du fait que jQuery, qui n'est que du JavaScript, n'accepte pas les requêtes cross-domain
    Pas de question technique par MP !
    Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
    Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
    Mon livre sur jQuery
    Module Firefox / Chrome d'intégration de JSFiddle et CodePen sur le forum

  3. #3
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    janvier 2008
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2008
    Messages : 253
    Points : 84
    Points
    84

    Par défaut

    Citation Envoyé par Bovino Voir le message
    jQuery, qui n'est que du JavaScript, n'accepte pas les requêtes cross-domain
    Bonjour Bovino, merci de ta réponse.

    Je me permets de te poser la question de but en blanc : Alors à quoi sert le paramètre "crossDomain" dans les options de la fonction ajax() ?
    Cela fait deux ans que j'utilise le hack avec YQL et jQuery arrive sans problèmes à me charger du HTML depuis mon sous-domaine racine.exemple.com vers d'autres sous-domaines.

    Voici un exemple qui fonctionne avec l'interface de la carte : on observe clairement la période de build après le chargement du DOM, tout le HTML de l'interface est chargé depuis un autre domaine que le www
    http://www.infos-reseaux.com/apps/AD...=webVRD_client

    Alors pourquoi cela serait-il différent pour mon fichier .ini?

  4. #4
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    février 2009
    Messages
    6 014
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : février 2009
    Messages : 6 014
    Points : 21 945
    Points
    21 945
    Billets dans le blog
    60

    Par défaut

    Bonsoir

    Citation de la FAQ jQuery :
    En raison de restrictions de sécurité imposées par Cross-Origin Resource Sharing, les transactions AJAX sont soumises à la politique de même origine, la requête AJAX ne parvient pas à récupérer les données d'un autre domaine, d'un sous domaine, ou d'un autre protocole. Seules les transactions AJAX manipulant des scripts et du JSONP ne sont pas soumises à ces restrictions.
    Extrait de la documentation AJAX :

    crossDomain(added 1.5) Default: false for same-domain requests, true for cross-domain requests

    If you wish to force a crossDomain request (such as JSONP) on the same domain, set the value of crossDomain to true. This allows, for example, server-side redirection to another domain
    asyncBoolean Default: true

    By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.

    Blog



    Nota bene : si vous devez être compatible avec les navigateurs obsolètes (IE8 et plus), vous devez convertir les codes ES2015 en ES5 avec Babel.

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  5. #5
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    janvier 2008
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2008
    Messages : 253
    Points : 84
    Points
    84

    Par défaut

    Bonsoir Danihagnoul, merci de ta réponse.

    En fait pour moi les deux premières citations sont contradictoires, AJAX peut s'appuyer sur des requêtes cross-domain depuis l'intronisation de l'XDomainRequest, ce que doit exploiter jQuery.
    C'est pour cette raison que j'ai bâti mon raisonnement sur le fait que je pouvais faire du cross-domain. Et le hack qui consiste à appeler YQL qui lui-même va chercher la ressource désirée marchait avant l'apparition d'XDomainRequest.

    Bref, il est bien dommage que ce ne soit possible qu'en asynchrone comme le laisse entendre la 3ième citation mais je m'en contenterai. J'ai toujours un message d'erreur même si ce n'est plus le même sous FF4:

    -Sous FF4 :
    Erreur de chargement du fichier 'http://racine.exemple.com/config.ini' : (error - )
    -Sous IE9 :
    Erreur de chargement du fichier 'http://racine.exemple.com/config.ini' : undefined (erreur - Erreur : Accès refusé).
    Inutile d'affirmer que j'ai la certitude que mon fichier existe bien sur le serveur
    Mais alors pourquoi cela ne fonctionne-t-il pas?

  6. #6
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    février 2009
    Messages
    6 014
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : février 2009
    Messages : 6 014
    Points : 21 945
    Points
    21 945
    Billets dans le blog
    60

    Par défaut

    Bonsoir

    Je ne suis pas un expert en AJAX et en PHP, mais je crois savoir que :
    • l'XMLHttpRequest cross-domain (la version 2 de l'XMLHttpRequest) n'est pas implémenté par tous les navigateurs ;
    • que le site appelé doit autoriser la transaction par un : header("Access-Control-Allow-Origin: *"); ;
    • que XDomainRequest() est spécifique à IE.

    Blog



    Nota bene : si vous devez être compatible avec les navigateurs obsolètes (IE8 et plus), vous devez convertir les codes ES2015 en ES5 avec Babel.

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  7. #7
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    janvier 2008
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2008
    Messages : 253
    Points : 84
    Points
    84

    Par défaut

    Très bien, je prends bonne note de tout cela.

    Cependant pour la deuxième remarque, c'est ce que j'ai cherché à faire pendant un temps mais vu qu'il s'agit d'un fichier à part entière non généré par PHP, je me demande comment je peux spécifier des en-têtes supplémentaires.
    En passant par un fichier htaccess peut-être?

    Dans un contexte plus large, il m’intéresserait également de ne rendre disponibles les ressources de mon sous-domaine racine.exempl... qu'à seulement tout autre sous-domaine du domaine principal vu qu'il s'agit de ressources annexes (images/css/js) et non de contenu à proprement parler.

    Cette modification solutionnera peut-être mon problème, peux-tu m'en dire plus?

  8. #8
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    février 2009
    Messages
    6 014
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : février 2009
    Messages : 6 014
    Points : 21 945
    Points
    21 945
    Billets dans le blog
    60

    Par défaut

    Bonjour

    On peut bien entendu limiter l'autorisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <?php
    header("Access-Control-Allow-Origin: *");              // Tous les domaines
    header("Access-Control-Allow-Origin: developpez.com");    // Seuls developpez.com et ses sous-domaines peuvent y accéder
    ?>
    Pour plus d'options, voir : Cross-Origin Resource Sharing

    Je n'ai jamais utilisé le Cross-domain, vous en savez maintenant plus que moi. Mais sur le forum PHP il y a sûrement quelqu'un de plus compétent sur ce sujet.

    [Edit]

    Citation de la FAQ jQuery : Comment dois-je formuler une requête AJAX ?

    Nota bene :

    À cause des restrictions imposées par : Cross-Origin Resource Sharing, sans un serveur pour donner les réponses attendues par le navigateur on n'obtient plus que des erreurs et des avertissements.

    Ainsi je n'arrive plus à travailler sur mon ordinateur avec un simple fichier JSON et une page HTML affichée dans Firefox 3.6.13 ou Chrome 9.0.597.86. Je suis obligé de sauvegarder la page web (qui ne contient pourtant que du code HTML) comme une page PHP et d'utiliser un serveur PHP (WampServer).

    Blog



    Nota bene : si vous devez être compatible avec les navigateurs obsolètes (IE8 et plus), vous devez convertir les codes ES2015 en ES5 avec Babel.

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  9. #9
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    juin 2008
    Messages
    23 648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2008
    Messages : 23 648
    Points : 91 557
    Points
    91 557
    Billets dans le blog
    20

    Par défaut

    Citation Envoyé par fanfouer
    Alors à quoi sert le paramètre "crossDomain" dans les options de la fonction ajax() ?
    Le code jQuery répondra mieux que moi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    if ( s.crossDomain ) {
     
    		var script,
    			head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
     
    		return {
     
    			send: function( _, callback ) {
     
    				script = document.createElement( "script" );
     
    				script.async = "async";
     
    				if ( s.scriptCharset ) {
    					script.charset = s.scriptCharset;
    				}
     
    				script.src = s.url;
    Comme l'a déjà indiqué Daniel, crossDomain, qui ne s'applique qu'aux scripts permet de créer une balise script et de l'intégrer dans la page. Ce qui explique aussi l'impossibilité de mode synchrone puisque seuls les scripts rencontrés avant la fermeture du DOM sont chargés de façon synchrone.
    Pas de question technique par MP !
    Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
    Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
    Mon livre sur jQuery
    Module Firefox / Chrome d'intégration de JSFiddle et CodePen sur le forum

  10. #10
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    janvier 2008
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2008
    Messages : 253
    Points : 84
    Points
    84

    Par défaut

    Citation Envoyé par danielhagnoul Voir le message
    Bonjour

    On peut bien entendu limiter l'autorisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <?php
    header("Access-Control-Allow-Origin: *");              // Tous les domaines
    header("Access-Control-Allow-Origin: developpez.com");    // Seuls developpez.com et ses sous-domaines peuvent y accéder
    ?>
    Pour plus d'options, voir : Cross-Origin Resource Sharing
    Vu que tout cela est pour PHP et que je ne me demande même pas si on peut modifier les vhosts Apache chez un hébergeur mutualisé bien connu, j'ai créé un script PHP qui m'affiche le contenu de mon fichier ini bit à bit et qui modifie les headers au passage avec le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    header ("Access-Control-Allow-Origin:*", true);
     
    $file = $_GET["file"];
     
    if (is_file ("./".$file.".ini")){
    	header ("Content-Type:text/plain");
     
    	readfile("./".$file.".ini");
    }else{
    	echo "404";
    }
    Les appels aux fichiers se feront donc comme ça : http://racine.exemple.com/getFile?file=config

    J'ai les en-têtes HTTP suivante dans la réponse
    HTTP/1.1 200 OK
    Date: Sun, 12 Jun 2011 14:18:15 GMT
    Server: Apache/2.2.X (OVH)
    X-Powered-By: PHP/5.3.5
    Access-Control-Allow-Origin: *
    Vary: Accept-Encoding
    Content-Encoding: gzip
    Content-Length: 85
    Keep-Alive: timeout=5, max=100
    Connection: Keep-Alive
    Content-Type: text/plain
    X-Antivirus: avast! 4
    X-Antivirus-Status: Clean
    Mais ca ne marche pas mieux qu'avant

    Je n'ai jamais utilisé le Cross-domain, vous en savez maintenant plus que moi. Mais sur le forum PHP il y a sûrement quelqu'un de plus compétent sur ce sujet.
    Je ne pense pas que ce soit un problème de PHP puisque j'ai les en-têtes attendues. C'est du côté du navigateur (plus que de jQUery même) que ça coince.

    Citation Envoyé par Bovino Voir le message
    Comme l'a déjà indiqué Daniel, crossDomain, qui ne s'applique qu'aux scripts permet de créer une balise script et de l'intégrer dans la page. Ce qui explique aussi l'impossibilité de mode synchrone puisque seuls les scripts rencontrés avant la fermeture du DOM sont chargés de façon synchrone.
    D'accord je comprends mieux, merci pour la précision.
    En l’occurrence, je travaille avec des fichiers ini donc pas de JSONP ou de <script/>. J'ai repassé crossDomain à false et je peux donc refaire du chargement synchrone mais j’obtiens les même messages que ceux évoqués dans mon premier post, retour à la case départ.

  11. #11
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    janvier 2008
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2008
    Messages : 253
    Points : 84
    Points
    84

    Par défaut

    Bien j'ai une solution à apporter

    L'échange fonctionne maintenant normalement, j'ai du oublier de spécifier certains headers dans la réponse du serveur et probablement la méthode OPTIONS comme étant acceptée pour le cross-domain.

    Pour rappel et pour ceux qui liront ce topic dans 250 ans, j'utilise le code suivant Javascript pour charger le contenu de mes fichiers ini de configuration de mon côté client (pour un autre format, modifier principalement la valeur de dataType) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    $.ajax({
    	async:false,
    	crossDomain:false,
    	url:url,
    	method:"GET",
    	success:function (data){
    		file_details.content = data;
    	},
    	error:function (xhr, status, error){
    		alert("Erreur de chargement du fichier '"+url+"' : "+xhr.responseText+" ("+status+" - "+error+")");
    	},
    	dataType:'text'
    });
    Lors de la requête, le scénario est un peu plus compliqué qu'une demande AJAX standart : il y a d'abord une requête preflight, puis une requête normale (pour évaluer la politique cross-domain du site visé).
    La requête preflight est une HTTP/1.1 OPTIONS sur l'URL visée avec les en-têtes suivantes :
    Origin: http://sous-domaine.exemple.com
    Access-Control-Request-Method: GET
    Access-Control-Request-Headers: x-requested-with
    La réponse est un HTTP 200 OK avec les données et les en-têtes qui intéressent le navigateur :
    Access-Control-Allow-Origin: http://sous-domaine.exemple.com
    Access-Control-Allow-Methods: GET,OPTIONS
    Access-Control-Allow-Headers: x-requested-with
    Le navigateur compare donc ses infos avec celles du serveur et décide ou non d'envoyer une deuxième requête, GET cette fois, sans les en-têtes de contrôle d'accès. C'est à cet endroit que ça bloquait chez moi, merci wireshark.

    Ensuite tout se passe suivant la méthode standard.

    Vu que dans mon cas je souhaitait accéder à des fichiers binaires/text sans passer par PHP, voici le code définitif de mon proxy qui permet d'ajouter les en-têtes côté serveur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    header ("Access-Control-Allow-Origin:*", true);
    header ("Access-Control-Allow-Methods: GET,OPTIONS", true);
    header ("Access-Control-Allow-Headers: x-requested-with", true);
     
    $file = $_GET["file"];
     
    if (is_file ("./".$file.".ini")){
    	header ("Content-Type:text/plain");
     
    	readfile("./".$file.".ini");
     
     
    }else{
    	header ("HTTP/1.1 404 Not Found");
    	echo "404";
    }
    A noter qu'il n'est pas possible de spécifier un Access-Control-Allow-Origin de la forme *.exemple.com. C'est bien dommage.

    Merci à votre aide et bonne soirée

  12. #12
    Candidat au Club
    Profil pro
    Inscrit en
    octobre 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 3
    Points : 4
    Points
    4

    Par défaut 非yes

    Très bien, je prends bonne note de tout cela.

    Cependant pour la deuxième remarque, c'est ce que j'ai cherché à faire pendant un temps mais vu qu'il s'agit d'un fichier à part entière non généré par PHP, je me demande comment je peux spécifier des en-têtes supplémentaires.
    En passant par un fichier htaccess peut-être?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [ZF 1.9] Routage sous domaine qui ne fonctionne pas
    Par supertino7 dans le forum MVC
    Réponses: 0
    Dernier message: 25/05/2010, 14h28
  2. Jquery/AJAX function click qui ne fonctionne pas.
    Par prome dans le forum jQuery
    Réponses: 2
    Dernier message: 12/03/2009, 12h57
  3. [AJAX] J'ai un script AJAX qui ne fonctionne pas
    Par beegees dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 29/10/2008, 16h21
  4. Réponses: 2
    Dernier message: 20/08/2008, 23h09
  5. [AJAX] AJAX qui ne fonctionne pas sous IE
    Par tavarlindar dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 30/05/2008, 11h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo