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 trato $.get(url, callback)
de 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 origen nulo no está permitido por Access-Control-Allow-Origin.
Si consulto esa URL desde un navegador directamente, funciona bien. ¿Qué está pasando y puedo evitar esto? ¿Estoy redactando mi consulta incorrectamente, o es algo que Panoramio hace para obstaculizar lo que estoy tratando de hacer?
Google no mostró coincidencias útiles en el mensaje de error .
EDITAR
Aquí hay un código de muestra 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 ESTÁ MAL. 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...
});
});
fuente
iframe
que usteddocument.write
, por ejemplo?file:///C:/
). Noiframe
está involucrado.Respuestas:
Para el registro, por lo que puedo decir, tuviste 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 admite CORS (Cross-Origin Resource Sharing) para permitir XMLHttpRequest entre dominios si el servidor lo autorizó. Ahí es dondeAccess-Control-Allow-Origin
entró el encabezado.Creo que mencionaste que lo estabas ejecutando desde un archivo: // URL. Hay dos formas para que los encabezados CORS indiquen que un XHR de dominio cruzado está bien. Una es enviar
Access-Control-Allow-Origin: *
(que, si estaba llegando a Flickr a través de$.get
, deben haber estado haciendo) mientras que la otra era hacer eco de los contenidos delOrigin
encabezado. Sin embargo, lasfile://
URL producen un valor nuloOrigin
que no se puede autorizar mediante eco-back.El primero fue resuelto de forma indirecta por la sugerencia de Darin de usar
$.getJSON
. Hace un poco de magia cambiar el tipo de solicitud de su valor predeterminado de "json" a "jsonp" si ve la subcadenacallback=?
en la URL.Eso resolvió el segundo al no tratar de realizar una solicitud CORS desde una
file://
URL.Para aclarar a otras personas, aquí están las sencillas instrucciones de solución de problemas:
$.get
y establecerdataType
ajsonp
.$.getJSON
e incluidocallback=?
en la URL.http://
. Los scripts que se ejecutan a través defile://
tienen soporte limitado para CORS.fuente
callback=?
no funcionó para mí, pero lojsonp=?
hizo. ¿Alguna explicación para eso?http://
? ¿O hay una manera de simplemente abrir el archivo usando ese protocolo?Quizás necesite agregar un HEADER en su script llamado, esto es lo que tuve que hacer en PHP:
Más detalles en Dominio cruzado AJAX o servicios WEB (en francés).
fuente
Para un proyecto HTML simple:
Luego busque su archivo.
fuente
POST
solicitudes que obtiene:code 501, message Unsupported method ('POST')
para los google.Funciona para mí en Google Chrome v5.0.375.127 (recibo la alerta):
También te recomendaría usar el
$.getJSON()
método, ya que el anterior no funciona en IE8 (al menos en mi máquina):Puede 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 serán llamadas
processImages
. Así es como funciona el soporte JSONP de JQuery. Observe cómo estoy definiendo elcallback=?
para que pueda usar una función anónima. Puede leer más al respecto en la documentación .Otro comentario es que no debes llamar a eval. El parámetro pasado a su función anónima ya será analizado en JSON por jQuery.
fuente
?
entonces el JSON devuelto está rodeado de paréntesis. No define un parámetro para su función de devolución de llamada, y el valor dethis
no parece tener un objeto de respuesta (al menos, el.data
valor esnull
).callback=?
le dice a jQuery que genere un nombre de función aleatorio internamente, lo que resulta en una llamada a la función anónima a la que pasa.getJSON
. Apreciado.Mientras el servidor solicitado sea compatible con el formato de datos JSON, use la interfaz JSONP (JSON Padding). Le permite realizar solicitudes de dominio externo sin servidores proxy o encabezados sofisticados.
fuente
Es la misma política de origen , debe usar una interfaz JSON-P o un proxy que se ejecute en el mismo host.
fuente
Lo gestionamos a través del
http.conf
archivo (editado y luego reiniciamos el servicio HTTP):En el
Header set Access-Control-Allow-Origin "*"
, puede poner una URL precisa.fuente
Si está haciendo pruebas locales o llamando al archivo desde algo como
file://
entonces necesita deshabilitar la seguridad del navegador.En MAC:
open -a Google\ Chrome --args --disable-web-security
fuente
En mi caso, el mismo código funcionó bien en Firefox, pero no en Google Chrome. La consola JavaScript de Google Chrome dijo:
Tuve que soltar la parte www de la URL de Ajax para que coincida correctamente con la URL de origen y funcionó bien entonces.
fuente
No todos los servidores admiten jsonp. Requiere que el servidor configure la función de devolución de llamada en sus resultados. Lo uso para obtener respuestas json de sitios que devuelven json puro pero no admiten jsonp:
fuente
Yo uso el servidor Apache, así que he usado el módulo mod_proxy. Habilitar módulos:
Luego añade:
Finalmente, pase proxy-url a su script.
fuente
Como nota final, la documentación de Mozilla dice explícitamente que
Como consecuencia, no es simplemente una mala práctica usar '*'. Simplemente no funciona :)
fuente
Para PHP: esto funciona para mí en Chrome, Safari y Firefox
https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null
usando axios llame a php live services con file: //
fuente
header('Access-Control-Allow-Origin: '.( trim($_SERVER['HTTP_REFERER'],'/') ?:'null'),true);
que permite el origen cruzado de un servidor remoto a otro también y caigo en (cadena) nulo para el archivo local.También recibí el mismo error en Chrome (no probé otros navegadores). 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 se solucionó el problema. Soy un visitante web perezoso, por lo que casi nunca escribo el www, pero aparentemente en algunos casos es obligatorio.
fuente
Asegúrese de estar utilizando 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
fuente
Amigos
Me encontré con un problema similar. Pero usando Fiddler, pude llegar al 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 diagonal final. 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 política especificado your_client_url: / 'no es válido. No puede terminar con una barra diagonal".
Esto es realmente peculiar porque funcionó sin problemas en Internet Explorer, pero me dio dolor de cabeza al probar con Google Chrome.
Eliminé la barra diagonal 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.
Gracias Andy
fuente
Hay un pequeño problema en la solución publicada por CodeGroover arriba , donde si cambia un archivo, tendrá que reiniciar el servidor para usar realmente el archivo actualizado (al menos, en mi caso).
Así que buscando un poco, encontré este para usar:
Y luego servirá a las
http://localhost:8000
.fuente