- Detalles
- Por Juan Padial
- En Programación
- Visto: 15586
Hoy en día prácticamente cualquier lenguaje de programación en el lado del servidor web permite las solicitudes remotas de una u otra forma. Sin embargo, esta característica no está presente en el javascript ejecutado en el navegador del lado del cliente. Las llamadas ajax a diferentes dominios desde el que carga el javascript es algo "prohibido" por todos los navegadores modernos que se rigen por el llamado Same Origin Policy. Esto no es debido a ninguna razón técnica que impida a los navegadores realizar una solicitud HTTP a otros dominios sino que es algo achacado a motivos de seguridad. La llamada ajax es prohibida incluso entre subdominios diferentes.
Existen diferentes modos de saltarse la restricción del Same Origin Policy. Un método puede ser hacer la solicitud ajax a un script en tu propio domino y desde el servidor hacer la solicitud remota a otra dominio. Por ejemplo, puedes hacer la solicitud ajax a un archivo de nombre script.php, archivo que estaría localizado en el mismo dominio desde el que se carga el javascript, y en script.php puedes utilizar algún método para abrir una URL de otro dominio, por ejemplo mediante cURL, fopen o file_get_contents.
El método al que me voy a dedicar en este post es realizar la llamada ajax con jQuery usando jsonp como lenguaje de intercambio de datos. Este método es en esencia un ajax pero no técnicamente pues los datos cargados son en sí mismos una función javascript y por ello se permite su carga en el navegador aunque se solicte desde diferentes dominios.
¿Qué es jsonp?
jsonp es es la versión padding de json y el estándar actual para Esto es, json con padding, un complemento de uso de json que permite la obtención de datos desde diferente dominios ya que los datos devueltos son en formato json encapsulados en una función javascript ...... y los scripts pueden ser cargados desde diferentes dominios!!!!!!. Técnicamente jsonp no es ajax en absoluto ya que no usa XMLHttpRequest sino que se realiza insertando dinamicamente un script en el DOM de la página.
La respuesta en formato json es obtenida en una forma similar a esta:
{'uid': '68', 'username': 'paquito', 'status': 'disconected'}
Mientras que los datos jsonp vienen en una función javascript:
callback({'uid': '68', 'username': 'paquito', 'status': 'disconected'});
La función javascript devuelta (en este caso callback) debe ser especificada en el lado del servidor y conocida para configurar nuestra llamada ajax con jquery y jsonp correctamente. Esto lo veremos con un poco más de detalle más adelante.
¿Cómo usar jquery con jsonp?
Se puede usar jQuery para leer y trabajar con datos jsonp usando cualquiera de las siguientes funciones jQuery : getJSON(), ajax(), post() y getScript().
Veamos como usar ajax() y getJSON().
getJSON()
La función getJSON() es un atajo de la función ajax() cuándo los tipos de datos intercambiados están en formato json. Tiene la siguiente sintaxis:
$.getJSON(url,[datos enviados],function(datos devueltos));
Los [datos enviados] son opcionales y han de ir en formato json. Para hacer cross domain con jsonp y el método getJSON de jQuery, simplemente debemos especificar el callback como parámetro de la URL de la forma callback=? reemplezando callback por el nombre de la función callback utilizada en el servidor. Por ello decía antes que el nombre de esta función debe ser conocida para poder configurar la llamada ajax de jQuery. Por ejemplo, el API de Flickr utiliza "jsoncallback" y en este caso tendremos que poner en la URL el siguiente parámetro: jsoncallback=?.
Ejemplo:
<!DOCTYPE html>
<html>
<head>
<style>img{ height: 100px; float: left; }</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div id="contendor">
</div>
<script>
var url = "http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?";
var opciones = {tags: "white cat", tagmode: "any",format: "json"};
$.getJSON(
url,
opciones,
function(data) {
$.each(data.items, function(i,item){
$("<img/>").attr("src", item.media.m).appendTo("#contendor");
if ( i == 5 ) return false;
});
});
</script>
</body>
</html>
ajax()
Para usar la función .ajax() con jsonp simplemente se especifica que los tipos de datos son jsonp y el nombre de la función callback. Al hacer esto jQuery pone automáticamente el parámetro callback=? al final de la url solicitada. Si es necesario especificar otro callback debes ponerlo específicamente. Por ejemplo, en el caso mencionado antes de Flickr, quedaría:
.ajax({
//....aquí usarías .ajax() de forma normal
dataType: 'jsonp',
callback: 'jsoncallback',
//....sigues usando .ajax() de forma normal
}):
jQuery recibirá los datos jsonp y los trata de forma igual a como lo hace con json. Si recordamos el ejemplo de ajax con jquery, php y json y lo queremos adaptar para que funcione en ajax cross domain, tendríamos que cambiar el código de jQuery para especificar el tipo de datos y la función callback y también el código PHP para que devuelva los datos en formato jsonp en lugar de json y con el callback deseado. Supongamos que el nombre del callback que queremos usar es mycallback:
$.ajax({
data: "id=2",
type: "GET",
dataType: "jsonp",
callback: "mycallback"
url: "http://www.miweb.com/casas.php",
success: function(data){
restults(data);
}
});
Ahora el script al que apunta la solicitud cambiaríamos las últimas líneas del código (para el código completo del ejemplo mencionado visita el post mencionado).
$jsondata['id'] = $row->id; $jsondata['m2'] = $row->m2; $jsondata['hab'] = $row->hab; $jsondata['direccion'] = $row->direccion; $json = json_encode($jsondata);
if($_GET['mycallback']) { echo $_GET['mycallback']."(".$json.")"; } else { echo $json; }
Puedes ver que se verifica la existencia del callback a través de $_GET['mycallback'] para devolver los datos en formato jsonp o, en caso contrario, en formato json simple. Cómo ves, es totalmente necesario conocer la función callback utilizada en el servidor. Si tú controlas el servidor del dominio remoto no tendrás problema en configurar correctamente el ajax cross domain con jQuery. Si no controlas el script del dominio remoto deberás conocer el nombre de la función callback utilizada preguntado o consultado el API del sitio.
El futuro del cross domain ajax
Dado el uso casi universal de ajax en cualquier proyecto web y la creciente interacción entre diferentes servicios alojados en diferentes dominios, la W3C está trabajando en la especificación Cross-Origin Resource Sharing (CROS - Recursos Compartidos desde Origen Diferente). Mediante esta especificación se envía la información del Origen de la solicitud al otro dominio y este, tras comprobar esta información, aprueba o no la solicitud cross-domain. Pero hasta que esta especificación se convierta en estándar habrá que seguir utilizando otros métodos para realizar una solicitud ajax entre diferentes dominios.
Y después de que el CROS sea un estándar, aún pueden pasar muchos años hasta que la mayoría de usuarios de internet utilicen navegadores que admitan esta tecnología y ya no exista la restricción del mismo origen en la solicitudes ajax.
jQuery cuenta, desde la versión 1.5, con el parámetro crossDomain en la configuración de los métodos ajax. El valor de este parámetro es false por defecto. Al especificar un callback en el método getJSON o al especificar jsonp como tipo de datos en el método ajax(), el valor del parámetro crossDomain pasa a ser true de forma automática. Si crossDomain tiene valor true, jQuery enviará las cabeceras adecuadas especificadas en la sintaxis CROS.
Creado el 19 05 2011 Actualizado el 05 02 2013
