AJAX Cross-Domain: JSONP + PHP

En ocasiciones nos encontramos con la necesidad de hacer uso de un servicio web o API externo a nuestro sitio a través de AJAX. Por defecto los navegadores tienen una politica que impide realizar peticiones a otro dominio por razones de seguridad.

Para solventar este problema Bob Ippolito en 2005 propuso el uso de una versión modificada de JSON denominada JSONP. A partir de entonces, muchos sitios y servicios han utilizado esta técnica para que se puedan consumir sus APIs desde una aplicación del lado del cliente.

Hasta hace un par de días, personalmente sólo había utilizado esta técnica desde el lado del consumidor, me parecía algo muy útil, pero nunca me había preocupado del lado del servidor, pero hace poco tuve que implementar un servicio web que debería poder ser accedido a través de una aplicación cliente alojado en otro servidor, por lo que tuve que ponerme a enterarme, y os traigo un tutorial con lo que he aprendido, pongo información tanto del lado del servidor (utilizando PHP), como del lado del cliente (utilizando jQuery).

Lado del servidor

Según la documentación de JSONP, se debe permitir que el cliente añada algo de contenido al JSON devuelto, siendo este englobado en paréntesis, básicamente para que lo que se devuelva sea la “ejecución de un función”, que será creada (de la forma que sea) en el cliente, para su ejecución al finalizar la llamada AJAX.

Por lo tanto, la idea básica es, teniendo un servicio web que devuelva un JSON válido, permitir dos nuevos parámetros: uno para representar el formato que diferenciará las llamadas remotas de las realizadas desde nuestra aplicación (si la hubiera) y otro, el nombre de la función a ejecutar en el cliente. Los nombres típicos de estos parámetros son format (con valor jsonp) y callback (o jsoncallback), aunque no es obligatorio.

El código (en PHP), podría ser algo como:


$format = $_REQUEST['format'];
if($format == "json") {
    if(isset($_REQUEST['callback'])) {
        $callback = $_REQUEST['callback'];
        echo "$callback(" . json_encode($json) . ")";
    } else {
        echo "callbackFunction(" . json_encode($json) . ")";
    }
}

De esta manera, si no se indica una función, indicamos una por defecto, otra opción es no permitirlo y devolver error.
el objecto $json sería la representación de lo que se devolvía desde un principio en el servicio web. Como veis, unicamente hay que concatenar el nombre de la función pasada y los paréntesis. Sencillo, no?

Lado del cliente

Posiblemente sea más conocido, además de que hay muchas formas diferentes de hacerlo, pero voy a poner dos ejemplos usando jQuery.

El primero es la versión más simplista utilizando la función getJSON y la segunda, utilizando la función AJAX completa, con una función aparte incluida.


jQuery.getJSON("http://url.com/directorio/fichero.php?param1=valor1&format=json&callback=?, function(data)
    console.log(data);
}");

 

Con lo que tendríamos una llamada a un JSON que ejecuta la función anónima indicada, en este caso tan simple como imprimir por consola, pero hay iría la lógica, tan complidada como lo que se quiera hacer.

La versión extendida, podría ser:


function logicaCliente(data){
    console.log(data);
}
jQuery.ajax({
    "url": "http://url.com/directorio/fichero.php?param1=valor1&format=json",
    "dataType": "jsonp",
    jsonpCallback: 'logicaCliente'
});

 

Existen multiples variantes de la forma de hacer esto, pero espero que aquellos que en algún momento se encontraran, como yo, perdidos, puedan encontrar ayuda en este pequeño tutorial.

Fuentes:

Blog de Bob Ippolito

Use Jquery

jQuery JSONP