597 votes

Erreur "Origin null is not allowed by Access-Control-Allow-Origin" pour une demande faite par une application s'exécutant depuis une URL file://.

Je suis en train de développer une page qui tire des images de Flickr et Panoramio via le support AJAX de jQuery.

Le côté Flickr fonctionne bien, mais lorsque j'essaie de $.get(url, callback) de Panoramio, je vois une erreur dans la console de Chrome :

XMLHttpRequest ne peut pas être chargé http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150 . L'origine null n'est pas autorisée par Access-Control-Allow-Origin.

Si j'interroge directement cette URL à partir d'un navigateur, tout fonctionne bien. Que se passe-t-il, et comment puis-je contourner ce problème ? Est-ce que je compose ma requête de manière incorrecte, ou est-ce que Panoramio fait quelque chose qui entrave ce que j'essaie de faire ?

Google n'a pas trouvé de correspondance utile sur le message d'erreur .

EDITAR

Voici un exemple de code qui montre le problème :

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';

  $.get(url, function (jsonp) {
    var processImages = function (data) {
      alert('ok');
    };

    eval(jsonp);
  });
});

Vous pouvez exécuter l'exemple en ligne .

EDIT 2

Merci à Darin pour son aide. LE CODE CI-DESSUS EST FAUX. Utilisez ceci à la place :

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';

  $.get(url, function (data) {
    // can use 'data' in here...
  });
});

1 votes

A quoi ressemble l'URL sur laquelle vous faites la demande ? de ? Il ne s'agit pas d'une génération dynamique. iframe que vous document.write dans, par exemple ?

7 votes

Pouvez-vous afficher la réponse HTTP de la demande à chaque service. Je parie que Panoramio ne répond pas à la requête Access-Control-Allow-Origin. Voir w3.org/TR/cors par exemple.

2 votes

@Kevin, vous n'avez pas besoin de ces en-têtes si le serveur envoie JSONP.

441voto

ssokolow Points 6549

Pour le compte rendu, pour autant que je sache, vous aviez deux problèmes :

  1. Vous n'avez pas passé un spécificateur de type "jsonp" à votre fichier $.get Il a donc utilisé un XMLHttpRequest ordinaire. Toutefois, votre navigateur prenait en charge la fonction CORS (Cross-Origin Resource Sharing) pour autoriser les requêtes XMLHttpRequest interdomaines si le serveur l'acceptait. C'est là que le Access-Control-Allow-Origin L'en-tête est arrivé.

  2. Je crois que vous avez mentionné que vous l'exécutiez à partir d'une URL file://. Il existe deux façons pour les en-têtes CORS de signaler qu'un XHR inter-domaine est OK. La première consiste à envoyer Access-Control-Allow-Origin: * (qui, si vous atteigniez Flickr via $.get ), tandis que l'autre devait renvoyer le contenu de l'adresse de l'utilisateur. Origin tête. Cependant, file:// Les URLs produisent un résultat nul Origin qui ne peut pas être autorisé par le biais de l'écho-back.

La première a été résolue de manière détournée par la suggestion de Darin d'utiliser $.getJSON . Il fait un peu de magie pour changer le type de requête de son défaut de "json" à "jsonp" s'il voit la sous-chaîne callback=? dans l'URL.

Cela a permis de résoudre la seconde en n'essayant plus d'exécuter une requête CORS à partir d'une file:// URL.

Afin de clarifier la situation pour les autres personnes, voici les instructions simples de dépannage :

  1. Si vous essayez d'utiliser JSONP, assurez-vous que l'une des conditions suivantes est remplie :
    • Vous utilisez $.get et mettre dataType a jsonp .
    • Vous utilisez $.getJSON et comprend callback=? dans l'URL.
  2. Si vous essayez de faire une requête XMLHttp inter-domaine via CORS...
    1. Assurez-vous que vous faites des tests via http:// . scripts en cours d'exécution via file:// ont un support limité pour CORS.
    2. Assurez-vous que le navigateur supporte effectivement CORS . (Opera et Internet Explorer sont en retard pour la fête)

55 votes

Quelle est donc la solution à ce problème ?

12 votes

Certains navigateurs, comme chrome, autorisent CORS s'ils sont lancés avec le paramètre --allow-file-access-from-files.

1 votes

callback=? n'a pas fonctionné pour moi, mais jsonp=? a fait. Une explication à cela ?

78voto

Thomas Decaux Points 2613

Vous devez peut-être ajouter un HEADER dans votre script, voici ce que j'ai dû faire en PHP :

header('Access-Control-Allow-Origin: *');

Plus de détails dans Cross domain AJAX ou services WEB (en français).

1 votes

@Uri : Cela dépend de votre serveur HTTP. Avec Apache, il faut regarder du côté de mod_headers.

4 votes

@Uri <meta http-equiv="Access-Control-Allow-Origin" content="*">

7 votes

@HerberthAmaral J'ai essayé d'ajouter ceci à l'intérieur de <head></head>, mais cela ne fonctionne pas pour moi. Je l'essaie dans iOS Safari et Chrome, mais dans la console, j'obtiens l'erreur origin null is not allowed by Access-Control-Allow-Origin.

77voto

CodeGroover Points 1425

Pour un projet HTML simple :

cd project
python -m SimpleHTTPServer 8000

Ensuite, parcourez votre fichier.

1 votes

Bien qu'il soit génial et qu'il fonctionne, lorsque vous allez à 0.0.0.0:8000 et que vous essayez POST les demandes que vous recevez : code 501, message Unsupported method ('POST') pour les googles.

0 votes

"Lorsqu'un serveur web Python (comme cherrypy par exemple) indique qu'il sert sur 0.0.0.0, cela signifie qu'il écoute tout le trafic TCP qui aboutit sur cette machine, quel que soit le nom d'hôte ou l'IP demandé." Essayez donc de poster sur localhost:8000. stackoverflow.com/a/4341808/102022

1 votes

Version de python3 : python -m http.server 8000

22voto

Darin Dimitrov Points 528142

Cela fonctionne pour moi sur Google Chrome v5.0.375.127 (je reçois l'alerte) :

$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
    alert(json.photos[1].photoUrl);
});

Je vous recommande également d'utiliser le $.getJSON() car la méthode précédente ne fonctionne pas avec IE8 (du moins sur ma machine) :

$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150', 
function(json) {
    alert(json.photos[1].photoUrl);
});

Vous pouvez l'essayer en ligne à partir d'ici .


UPDATE :

Maintenant que vous avez montré votre code, je peux voir le problème qu'il pose. Vous avez à la fois une fonction anonyme et une fonction en ligne mais les deux seront appelées. processImages . C'est ainsi que le support JSONP de jQuery fonctionne. Remarquez comment je définis le callback=? afin de pouvoir utiliser une fonction anonyme. Vous pouvez lire la suite à ce sujet dans la documentation .

Une autre remarque est que vous ne devriez pas appeler eval. Le paramètre passé à votre fonction anonyme sera déjà analysé en JSON par jQuery.

0 votes

Hmm ok laissez moi essayer à nouveau. Je suis sur une version différente de Chrome entre "6.0.472.51 beta".

0 votes

Votre code a également fonctionné pour moi. J'ai mis à jour ma question avec un code qui fait ressortir le problème.

0 votes

Merci pour l'astuce concernant getJSON... J'ai forké votre exemple jsFiddle pour montrer le problème ( jsfiddle.net/ZfvKm ) et je vois maintenant le message d'erreur _XMLHttpRequest ne peut pas être chargé panoramio.com/wapi/data/ . Origine fiddle.jshell.net n'est pas autorisé par Access-Control-Allow-Origin._

9voto

Cheng Chen Points 103

Tant que le serveur demandé prend en charge le format de données JSON, utilisez l'interface JSONP (JSON Padding). Elle vous permet d'effectuer des requêtes de domaine externe sans serveur proxy ni en-tête fantaisiste.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X