Cómo la mayoría ya sabréis, los navegadores limitan las llamadas AJAX al mismo subdominio de la página web que las realiza, no siendo posible realizar llamadas AJAX fuera de este subdominio. Esto se hace por motivos de seguridad. Forma parte de lo que se conoce como same-origin policy.
Con el advenimiento de la nueva Web basada en APIs, es cada vez mas frecuente encontrarse con escenarios en los que la same-origin policy resulta demasiado restrictiva. Es por ello que desde hace algún tiempo vienen utilizándose diferentes técnicas para superar las limitaciones impuestas por la same-origin policy.
Para el caso que nos ocupa, que implica realizar llamadas AJAX desde un subdominio distinto, existen varias técnicas posibles, como JSONP, pero yo me centraré en la que creo que tiene mas futuro, ya que viene impulsada por el W3C : CORS (Cross-origin resource sharing)
CORS consiste en una especificación estandarizada que añade nuevas cabeceras al protocolo HTTP. Estas cabeceras permiten al servidor ofrecer sus recursos a los subdominios de origen permitidos. Los navegadores deben soportar estas nuevas cabeceras y respetar las retricciones establecidas. Para evitar algunos efectos colaterales de utilizar diferentes métodos en las peticiones, el navegador debe comprobar cada petición utilizando una llamada con el método HTTP OPTIONS, y una vez obtenida la aprobación del servidor, enviar la llamada con el método necesario. Así mismo, los servidores también pueden notificar cuando es necesario presentar credenciales para el envío de una petición.
En nuestro caso concreto, queremos utilizar un servicio JSON-RPC ya existente, así que deberemos de parchear en el lado del servidor, asegurándonos de que se envían las cabeceras adecuadas. En PHP:
$referer_parts=parse_url($_SERVER[‘HTTP_ORIGIN’]);
$origin=$referer_parts[‘scheme’].»://».$referer_parts[‘host’];
header(«Access-Control-Allow-Origin: $origin»);
header(«Access-Control-Allow-Credentials: true»);
header(«Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept»);
header(«Vary: Origin»);
Así mismo, deberemos parchear en el lado del cliente, y asegurarnos de que la llamada AJAX incluya las cabeceras adecuadas. Si se está usando JQuery, deberéis añadir a los parámetros de la llamada AJAX:
$.ajax({
…
xhrFields: {withCredentials: true },
…
});
Realmente no termino de entender la necesidad de «withCredentials» en ambos lados (cliente y servidor), ya que no estoy usando ningún tipo de credencial para autentificar al cliente. Sin embargo, no he conseguido que funcione sin ponerlo. Si alguno tiene información al respecto, agradecería que la compartiese.
]]>Y probablemente es por este motivo que pocos programadores conocen o usan este magnífico proyecto de software libre que puede simplificarnos la vida en mas de una situación espinosa. A mi me ha resuelto el problema maravillosamente en dos ocasiones, y es por eso que os hablaré hoy de él.
Imaginad que estáis programando un sistema en el que es necesario generar un PDF de cierta complejidad y tamaño, utilizando datos de una BBDD. Por ejemplo, un cliente que os solicita la posibilidad de generar un catálogo en PDF con los productos de la BBDD de su plataforma de ecommerce.
La generación directa de PDF utilizando APIs como FPDF, TCPDF o PDFLib es pesada y engorrosa, sobre todo si el diseño gráfico es importante. Además, es costosa de mantener.
La otra opción que rápidamente nos viene a la cabeza es la de generar en HTML, y convertir luego a PDF. Es una opción que nos permite integrar fácilmente el diseño, además de ser mas fácil de mantener.
Pisaremos un terreno mucho mas confortable (HTML+CSS) y por si fuera poco, la previsualización del documento será trivial. Esto último es importante. Tened en cuenta que una conversión de HTML a PDF con imágenes de alta resolución aptas para impresión (300ppp) puede tardar minutos y ocupar muchos MB si el número de imágenes es considerable (>1000), así que conviene tener una buena previsualización antes de darle al botón de generar.
Existen algunos servicios on-line de conversión de HTML a PDF, como phptopdf.com, pero tienen limitaciones respecto al tamaño de los archivos generados, etc.
Así pues, nos queda el software de conversión propiamente dicho. Por supuesto, tenemos dónde elegir:
Mi consejo es que no perdáis el tiempo probándolos y uséis diréctamente wkhtmltopdf.
¿Por qué wkhtmltopdf?

Instalación
Si usáis Debian o Ubuntu:
$ sudo apt-get install wkhtmltopdf
Si usáis Fedora o RedHat/CentOS:
$ wget http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.1/wkhtmltox-0.12.1_linux-centos6-amd64.rpm
$ rpm -Uhv wkhtmltox-0.12.1_linux-centos6-amd64.rpm
Para otras opciones de instalación: wkhtmltopdf.org/downloads
Primer contacto
La manera mas sencilla de empezar a utilizar wkhtmltopdf es desde la linea de comandos:
$ wkhtmltopdf http://www.ethereum.org ethereum.pdf
Este sencillo comando generara un PDF a partir de una página web on-line.
Ejemplo en PHP
//Obtener Datos de la BBDD …
$data=db_query(«SELECT datos FROM db»);//Generar archivo HTML usando plantillas …
$buffer=template_proccess($tmpl_file,$data);
file_put_contents($html_file,$buffer);//Generar archivo PDF …
$global_opts=»-s A4 -B 10 -L 10 -R 10 -T 12″;
$page_opts=»–zoom 1.2 –footer-center ‘[page]/[topage]’ –footer-font-size 6 –no-footer-line»;
$cmd=»wkhtmltopdf $opts page ‘$html_file’ $page_opts ‘$pdf_file'»;
$result=shell_exec($cmd);if (!file_exists($pdf_file) || filesize($pdf_file)<1000) {
$message=gettext(«PDF generation error»).»: «.$pdf_file.»\n\n$cmd\n$result»;
throw new Exception($message);
}
El ejemplo utiliza algunos de los muchos parámetros que acepta el programa:
Para saber mas, ya sabéis, RTFM 
$ man wkhtml2pdf
Gracias a Jakob Truelsen y Ashish Kulkarni, los desarrolladores de wkhtmltopdf
]]>