javascript - habilitar - Error XmlHttpRequest: Access-Control-Allow-Origin no permite el origen nulo
jsonp javascript (16)
Estoy desarrollando una página que extrae imágenes de Flickr y Panoramio a través del soporte AJAX de jQuery.
El lado de Flickr funciona bien, pero cuando intento $.get(url, callback)
desde Panoramio, veo un error en la consola de Chrome:
XMLHttpRequest no puede cargar 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 . El nulo de origen no está permitido por Access-Control-Allow-Origin.
Si consulto esa URL directamente desde un navegador, funciona bien. ¿Qué está pasando, y puedo solucionar esto? ¿Estoy componiendo mi consulta incorrectamente, o esto es algo que Panoramio hace para impedir lo que estoy tratando de hacer?
Google no encontró ninguna coincidencia útil en el mensaje de error .
EDITAR
Aquí hay un código de ejemplo que muestra el problema:
$().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);
});
});
Puede ejecutar el ejemplo en línea .
Editar 2
Gracias a Darin por su ayuda con esto. EL CÓDIGO ANTERIOR ES INCORRECTO. Use esto en su lugar:
$().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...
});
});
Asegúrate de estar usando la última versión de JQuery. Nos enfrentamos a este error para JQuery 1.10.2 y el error se resolvió después de usar JQuery 1.11.1
Como nota final, la documentación de Mozilla dice explícitamente que
El ejemplo anterior fallaría si el encabezado fuera comodín como: Access-Control-Allow-Origin: *. Dado que Access-Control-Allow-Origin menciona explícitamente http: //foo.example , el contenido de credencial-conocedor se devuelve al contenido web que invoca.
Como consecuencia, no es simplemente una mala práctica usar ''*''. Simplemente no funciona :)
En mi caso, el mismo código funcionó bien en Firefox, pero no en Google Chrome. La consola de JavaScript de Google Chrome dijo:
XMLHttpRequest cannot load http://www.xyz.com/getZipInfo.php?zip=11234.
Origin http://xyz.com is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"
Tuve que quitar la parte www de la URL de Ajax para que coincidiera correctamente con la URL de origen y funcionó bien entonces.
Es la misma política de origen , tiene que usar una interfaz JSON-P o un proxy que se ejecute en el mismo host.
Funciona para mí en Google Chrome v5.0.375.127 (me da la alerta):
$.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);
});
También te recomendaría que $.getJSON()
método $.getJSON()
lugar de que el anterior no funciona en IE8 (al menos en mi máquina):
$.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);
});
Puedes probarlo en línea desde aquí .
ACTUALIZAR:
Ahora que ha mostrado su código, puedo ver el problema con él. Tiene una función anónima y una función en línea, pero ambas se processImages
. Así es como funciona el soporte JSONP de jQuery. Observe cómo estoy definiendo la callback=?
para que pueda utilizar una función anónima. Puede leer más $.getJSON() .
Otra observación es que no debes llamar a eval. El parámetro pasado a su función anónima ya será analizado en JSON por jQuery.
Gente
Me encontré con un problema similar. Pero usando Fiddler, pude entender el problema. El problema es que la URL del cliente que está configurada en la implementación de CORS en el lado de la API web no debe tener una barra inclinada hacia adelante. Después de enviar su solicitud a través de Google Chrome e inspeccionar la pestaña TextView de la sección Encabezados de Fiddler, el mensaje de error indica algo como esto:
* "El origen de la política especificada your_client_url: / ''no es válido. No puede terminar con una barra inclinada".
Esto es realmente peculiar porque funcionó sin problemas en Internet Explorer, pero me dio un dolor de cabeza al probar con Google Chrome.
Eliminé la barra inclinada en el código CORS y volví a compilar la API web, y ahora se puede acceder a la API a través de Chrome e Internet Explorer sin ningún problema. Por favor, dale una oportunidad a esto.
Gracias Andy
Hay un pequeño problema en la solución publicada por CodeGroover , donde si cambia un archivo, tendrá que reiniciar el servidor para usar el archivo actualizado (al menos, en mi caso).
Así que buscando un poco, encontré este para usar:
sudo npm -g install simple-http-server # to install
nserver # to use
Y luego servirá en http://localhost:8000
.
Lo gestionamos a través del archivo http.conf
(editamos y luego reiniciamos el servicio HTTP):
<Directory "/home/the directory_where_your_serverside_pages_is">
Header set Access-Control-Allow-Origin "*"
AllowOverride all
Order allow,deny
Allow from all
</Directory>
En el Header set Access-Control-Allow-Origin "*"
, puede poner una URL precisa.
Mientras el servidor solicitado admita el formato de datos JSON, use la interfaz JSONP (JSON Padding). Te permite realizar solicitudes de dominio externo sin servidores proxy o cosas de encabezado sofisticadas.
No todos los servidores soportan jsonp. Requiere que el servidor establezca la función de devolución de llamada en sus resultados. Uso esto para obtener respuestas de json de sitios que devuelven json puro pero no son compatibles con jsonp:
function AjaxFeed(){
return $.ajax({
url: ''http://somesite.com/somejsonfile.php'',
data: {something: true},
dataType: ''jsonp'',
/* Very important */
contentType: ''application/json'',
});
}
function GetData() {
AjaxFeed()
/* Everything worked okay. Hooray */
.done(function(data){
return data;
})
/* Okay jQuery is stupid manually fix things */
.fail(function(jqXHR) {
/* Build HTML and update */
var data = jQuery.parseJSON(jqXHR.responseText);
return data;
});
}
Para el registro, por lo que puedo decir, tuvo dos problemas:
No estaba pasando un especificador de tipo "jsonp" a su
$.get
, por lo que estaba usando un XMLHttpRequest ordinario. Sin embargo, su navegador admitió CORS (Intercambio de recursos de origen cruzado) para permitir XMLHttpRequest de dominio cruzado si el servidor lo aprobó. Ahí es donde entró el encabezadoAccess-Control-Allow-Origin
.Creo que mencionaste que lo estabas ejecutando desde un archivo: // URL. Hay dos formas en que los encabezados CORS indican que un XHR de dominio cruzado está bien. Una es enviar
Access-Control-Allow-Origin: *
(que, si llegaba a Flickr a través de$.get
, deben haber estado haciendo), mientras que la otra era devolver el contenido del encabezadoOrigin
. Sin embargo, las URL defile://
producen unOrigin
nulo que no se puede autorizar a través de la devolución.
El primero fue resuelto de forma indirecta por la sugerencia de Darin de usar $.getJSON
. Hace un poco de magia para cambiar el tipo de solicitud de su valor predeterminado de "json" a "jsonp" si ve la subcadena callback=?
en la URL.
Eso resolvió el segundo al no intentar realizar una solicitud CORS desde un file://
URL.
Para aclarar para otras personas, aquí están las sencillas instrucciones de resolución de problemas:
- Si está intentando usar JSONP, asegúrese de que uno de los siguientes es el caso:
- Estás usando
$.get
y establecedataType
enjsonp
. - Estás usando
$.getJSON
e incluyecallback=?
en la URL.
- Estás usando
- Si está tratando de hacer un XMLHttpRequest de dominio cruzado a través de CORS ...
- Asegúrese de que está probando a través de
http://
. Los scripts que se ejecutan a través defile://
tienen soporte limitado para CORS. - Asegúrese de que el navegador realmente admita CORS . (Opera e Internet Explorer llegan tarde a la fiesta)
- Asegúrese de que está probando a través de
Para un proyecto HTML simple:
cd project
python -m SimpleHTTPServer 8000
Luego navega por tu archivo.
Si está realizando pruebas locales o está llamando al archivo desde algo como file://
entonces necesita deshabilitar la seguridad del navegador.
En MAC: open -a Google/ Chrome --args --disable-web-security
Tal vez necesites agregar un HEADER en tu script llamado, esto es lo que tuve que hacer en PHP:
header(''Access-Control-Allow-Origin: *'');
Más detalles en Cross domain AJAX ou services WEB (en francés).
También recibí el mismo error en Chrome (no probé otros browers). Fue debido al hecho de que estaba navegando en domain.com en lugar de www.domain.com. Un poco extraño, pero podría resolver el problema agregando las siguientes líneas a .htaccess. Redirige domain.com a www.domain.com y el problema se resolvió. Soy un visitante perezoso de la web, por lo que casi nunca escribo el www, pero al parecer en algunos casos es necesario.
RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain/.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
Yo uso el servidor Apache, por lo que he usado mod_proxy módulo. Habilitar módulos:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Luego añade:
ProxyPass /your-proxy-url/ http://service-url:serviceport/
Finalmente, pase el proxy-url a su script.