Documentos de Académico
Documentos de Profesional
Documentos de Cultura
16.11.2005
9:01
Uhr
Pgina
53
Python DESARROLLO
AJAX
AJAX es la palabra de moda, Google usa AJAX, Yahoo usa AJAX todo el mundo quiere usar AJAX pero lo usas t? y ms importante an qu demonios es AJAX? POR JOS MARA RUIZ Y PEDRO ORANTES
Brave New World (Un Mundo Feliz) es el nombre de la famosa novela de Aldous Huxley, en ella nos muestra un mundo distinto y aterrador pero que pareca, y parece, cada vez ms cercano. Nosotros no tenemos una visin tan pesimista del mundo, pero es probable que ese ttulo (que se podra traducir literalmente por un nuevo y desafiante mundo) explique todo el revuelo que est levantando AJAX. El trmino fue acuado por Jesse James Garrett en el artculo [1] de la tabla Referencias. Durante mucho tiempo las GUIs, las Interfaces Grficas de Usuario, han dominado la informtica. La gente que trabajaba en la Web siempre estaba intentando convencer a todo el mundo de que para la mayora de los programas, un interfaz web bastaba. Pero los usuarios estaban acostumbrados a ciertas caractersticas, como el auto-completado
de campos o el arrastrar y soltar, que eran imposibles en la Web. Conforme avanzaba el tiempo numerosas empresas y personas proponan soluciones. La lista es interminable: JavaScript, Java Applets, ActiveX, Tcl, VBScript, Macromedia Flash Pero todas fallaban de uno u otra manera. En el caso de Java, para ejecutar el Applet necesitabas tener instalado el Java Runtime Environment, y la mayora de los usuarios no saban ni qu era aquello que se le peda. Lo mismo ocurra con Macromedia Flash. Lo peor era que cuando estaba solucionado el tema de la instalacin del software adecuado, los desarrolladores creaban, y crean, pginas horribles llenas de cosas movindose que distraen e irritan. Se sentan impulsados a usar hasta la ltima capacidad de las nuevas herramientas y acababan generando monstruosidades.
Esta fase ya casi ha pasado y ahora se busca la sencillez, y en el momento justo surgi AJAX. Para ms informacin ver url [2] de la tabla Referencias.
WWW.LINUX- MAGAZINE.ES
Nmero 12
53
053-060_PythonL12
16.11.2005
9:01
Uhr
Pgina
54
DESARROLLO Python
Pero qu es AJAX?
Muy buena pregunta. Lo cierto es que AJAX ha estado delante de nuestras narices todo el tiempo, esperando a que alguna mente despierta lo redescubriese. El acrnimo AJAX se compone de las palabras Asynchronous JavaScript and XML, trmino acuado por Jesse James Garrett, y curiosamente su existencia se debe a una de esas famosas violaciones de los estndares que suele realizar Microsoft con sus productos. All por 1998, Microsoft introdujo dentro de sus productos una librera que le permita hacer consultas usando el protocolo HTTP de manera autnoma y asncrona. Cuando tu navegador accede a una pgina y esta contiene cdigo Javascript, este cdigo a su vez puede traer informacin de esa u otras pginas de manera independiente. Si adems se hace que este cdigo permanezca en ejecucin respondiendo a eventos tenemos entre manos la
posibilidad de traer informacin al navegador sin recargar la pgina. Esto es til para algunas tareas pero no demasiado, ya que a nuestro puzzle le faltan piezas. La primera pieza es la adopcin de esta librera por casi todos los navegadores, por lo tanto el cdigo pasa a ser de aplicacin universal. Adems resulta que podemos modificar el contenido de la pgina en tiempo real usando el denominado rbol DOM. Y por si fuese poco, cuando AJAX fue definido, los programadores comenzaron a usar protocolos XML para comunicarse con los servidores. Qu quiere decir esto? Pues que ahora, con AJAX, podemos cargar una pgina y, sin tener que recargarla, traernos informacin, modificar la pgina en tiempo real, e interactuar con servidores remotos usando protocolos XML. Bsicamente, una vez cargada la pgina web tenemos entre manos todas las posibilidades de programacin de un GUI tradicional. Y todo esto sin necesidad de plugins ni instalaciones, toda esta tecnologa est en nuestros navegadores esperando ser usada.
ser consultado usando AJAX. Crearemos una web con algo de cdigo Javascript que a intervalos acceder a nuestro servidor Python y modificar el aspecto de la pgina web.
Los 5 Ingredientes
Los cinco ingredientes necesarios para elaborar nuestro producto son CSS, Javascript, HTML, XML y Python, como aparecen en la figura 1, y cada uno tiene su funcin en esta obra. HTML es la base sobre la que vamos a trabajar, definimos una pgina web en la que todo ocurrir. De hecho, con el paso del tiempo el propio HTML ha acabado convirtindose en una especie de plantilla donde campan a sus anchas CSS y Javascript. CSS nos permite otorgar propiedades visuales a los elementos de HTML. Javascript es el encargado de actuar en la mquina cliente, en el navegador, y puede modificar tanto el HTML como las propiedades visuales que CSS define. Con la llamada XMLHttpResponse sus atribuciones se han disparado. Ahora se ve como un lenguaje de programacin de pleno derecho. En los prximos aos puede que adquiera mucha ms importancia de la que ha tenido hasta ahora.
08 09 10 11 12 13 14 15
acciones = { "/" : ["envia_fichero","index.html"] , 16 "/ps.xml" : ["envia_comando", "ps afx"], 17 "/df.xml": ["envia_comando", "df"], 18 "/who.xml": ["envia_comando","who"],
if self.path in acciones.keys(): 22 accion = acciones[self.path] 23 (getattr(self,accion[0]))(self .path,accion[1]) 24 else: 25 if (self.path[-3:] == ".js" or 26 self.path[-4:] == ".css"): 27 self.envia_fichero("",self.pat h[1:]) 28 29 else: 30 self.envia_fichero("","404.htm l") 31 32 def
54
Nmero 12
WWW.LINUX- MAGAZINE.ES
053-060_PythonL12
16.11.2005
9:01
Uhr
Pgina
55
053-060_PythonL12
16.11.2005
9:01
Uhr
Pgina
56
DESARROLLO Python
XML es el nuevo lenguaje estndar de intercambio de informacin. Prcticamente cualquier lenguaje dispone ya de libreras para generar y analizar documentos XML. Dentro del mundillo AJAX se ha convertido en el estndar para el intercambio de informacin con el servidor y para la serializacin de objetos con protocolos como JSON. Y, como no, Python. En nuestro caso se va a encargar tanto de realizar las tareas de servidor HTTP como de recolectar informacin importante y confeccionar con ella ficheros XML. Tenemos que compenetrar todos estos elementos para realizar nuestro proyecto. El objetivo es que los componentes HTML, Javascript, CSS y XML sean tan estticos como sea posible, debido a que todos ellos interactan con el usuario. Es en el servidor Python donde debemos aportar la flexibilidad necesaria como para aadir nuevas caractersticas sin tener que cambiar ninguno de los otros elementos.
mos BaseHttpRequest. Esta clase nos permite construir servidores HTTP sin excesivo esfuerzo, as que la emplearemos. Pero no debemos usarla directamente, sino a travs de la clase BaseHttpRequestHandler, que es la encargada de gestionar los eventos que se suceden en el servidor. Por tanto heredaremos de ella y crearemos una clase llamada AJAXHttpRequestHandler, ver Listado 1 (todos los listados de este artculo pueden descargarse de [4]). Un servidor HTTP recibe distintos tipos de comandos, pero el que nos inte-
resa es el comando GET. Es el usado para solicitar informacin al servidor. Cada vez que se realice una peticin GET se invocar el mtodo do_GET de BaseHTTPRequestHandler as que lo vamos a redefinir en nuestra clase. Cuando se invoque do_GET, en la variable de instancia self.path se encuentra la ruta solicitada por el cliente. Nosotros contrastaremos esta ruta contra las que aceptamos. Si no se encuentra entre ellas, devolveremos la clebre pgina 404, indicando que la pgina solicitada no existe. La informacin se devuelve
+ "</linea>" 85 linea = self.tuberia.readline()[:-1] 86 self.xml += "</salida>" 87 return self.xml 88 89 def tipo(self): 90 return "xml" 91 92 def test(HandlerClass = AJAXHTTPRequestHandler, 93 ServerClass = BaseHTTPServer.HTTPServer): 94 BaseHTTPServer.test(HandlerCla ss, ServerClass) 95 96 if __name__ == '__main__': 97 test()
56
Nmero 12
WWW.LINUX- MAGAZINE.ES
053-060_PythonL12
16.11.2005
9:01
Uhr
Pgina
57
Python DESARROLLO
usando el mtodo self.wfile.write(), lo que en l escribamos, ser devuelto al cliente que realiz la peticin. Adems del fichero index.html, ofreceremos una serie de servicios en forma de ficheros XML. Estos servicios consistirn en la ejecucin de un comando de sistema, y la conversin de su salida en un fichero XML. El formato del fichero ser muy sencillo:
desde envia_respuesta antes de enviar el fichero en s. Es de esta manera como el navegador determina el tipo de fichero que recibe y sus caractersticas. Cuando arranquemos el servidor, veremos que van apareciendo mensajes correspondientes a los distintos comandos que se le mandan. La clase BaseHTTPRequest genera una entrada por cada una. Ver figura 2.
<?xml version="1.0"?> <salida> <linea>linea de salida</linea> ... <linea>linea de salida</linea> ... <linea>linea de salida</linea> </salida>
Gestores de servicios
Para gestionar los servicios se han creado las clases Pagina y Comando, que responden a los mismos mtodos. La primera, Pagina, se encarga de las peticiones de ficheros de texto, que en nuestro programa se reducen al fichero index.html y sus ficheros supletorios, fichero Javascript y CSS. Bsicamente los carga en una variable y, mediante el mtodo contenido, las dems clases tienen accesos a los mismos. En este caso, el parmetro ruta no afecta a esta clase, pero se ha definido para que guarde compatibilidad con la clase Comando. La clase Comando ejecuta el comando especificado y permite el acceso al texto devuelto por l mismo mediante el mismo mtodo que la clase Pagina. De esta manera son intercambiables. Ambas clases poseen un mtodo tipo() que devuelve el tipo de fichero que almacenan. En el caso de Comando, siempre ser un fichero XML, pero Pagina debe adivinar el tipo de los ficheros que
Por lo que generaremos el fichero XML a mano, sin hacer uso de libreras. De esta manera, cuando el cliente solicite el fichero ps.xml, nuestro servidor ejecutar el comando ps afx, crear el fichero ps.xml con la salida del comando y se lo enviar al cliente.
Definicin de servicios
Para permitir que la definicin de servicios sea lo ms simple posible, basta con introducir una nueva entrada en el diccionario acciones de la clase AJAXHTTPRequestHandler con la siguiente estructura:
<ruta> : [<mtodo_a_invocar>,U <comando_a_ejecutar>],
Cuando se gestiona el comando HTTP GET, se busca en este diccionario la ruta. En caso de que est presente, se ejecutar el mtodo almacenado usando como parmetros la ruta y el comando. Esto nos da gran flexibilidad, aadir un nuevo servicio consiste en introducir una nueva linea de cdigo. Existe un detalle importante, todo fichero devuelto usando HTTP debe tener una cabecera con una serie de lneas con formato llave: valor que dan informacin al cliente, el navegador, sobre el fichero devuelto. Debido a problemas de espacio hemos decidido devolver slo el formato del fichero. Para ello se invoca el mtodo envia_cabecera
WWW.LINUX- MAGAZINE.ES
Nmero 12
57
053-060_PythonL12
16.11.2005
9:01
Uhr
Pgina
58
DESARROLLO Python
devuelve. Para ello se comprueba la extensin de los mismos. En aras de la simplicidad, slo consideraremos tres extensiones. Cuando un comando es ejecutado por Comando, se tiene especial cuidado en utilizar la funcin cgi.escape sobre cada linea. Esta funcin realiza algunas conversiones dentro del texto que se le pasa para que pueda ser correctamente visualizado por un navegador web. El problema radica en que ciertos caracteres, como pueden ser < or son especiales y si no se escapan, si no se preceden de un \, causarn problemas. Y con esto, hemos definido un servidor web bsico. Python nos permite realizar complejas tareas con poco cdigo y
este es uno de esos casos. Vayamos ahora a por AJAX para comprenderlo.
HTML
Quiz ste sea uno de los artculos donde Python tenga menor protagonismo, pero con cinco actores suele ser complicado. Veamos el HTML. La pgina index.html se puede ver en el Listado 2. Bsicamente carga un fichero Javascript, un fichero CSS y muestra un ttulo junto a unos cuantos botones. Estos botones invocan acciones en Javascript. Debemos fijarnos especialmente en el uso del atributo id en numerosas etiquetas HTML. Gracias a estos ids podremos manipularlas mediante Javascript.
27
28 29
30 31
32 33 34 35 // Carga el resultado del XML 36 function modificaContenido() { 37 if (http_request.readyState == 4) { 38 if (http_request.status == 200) { 39 vaciaContenido(); 40 41 var xmldoc = http_request.responseXML; 42 var root = xmldoc.getElementsByTagName('s alida').item(0); 43 44 var fondo = 0; 45 46 for(var i = 0; i < root.childNodes.length; i++){
var contenedor = document.getElementById("contenedor"); 50 var p = document.createElement("p"); 51 52 // Truco para los colores ;) 53 if (fondo == 0) { 54 p.setAttribute("id","linea0"); } 55 else { 56 p.setAttribute("id","linea1"); 57 } 58 fondo = 1 - fondo; 59 60 var titulo = document.getElementById("datos"); 61 p.textContent = nodo.firstChild.data; 62 63 contenedor.insertBefore(p,titu lo); 64 } 65 66 } else { 67 alert('Hubo un problema con la peticin.'); 68 } 69 } 70 }
58
Nmero 12
WWW.LINUX- MAGAZINE.ES
053-060_PythonL12
16.11.2005
9:02
Uhr
Pgina
59
053-060_PythonL12
16.11.2005
9:02
Uhr
Pgina
60
DESARROLLO Python
mente nada que ver, aparte del nombre. En nuestro ejemplo vemos tres funciones: hazPeticion() modificaContenido() vaciaContenido() Javascript, adems de muchas de las caractersticas presentes Figura 3: Nuestra pgina devolver los resultados de en otros lenguajes (y algunas la consulta sin recargar. ausentes) dispone de una coleccin de objetos que le permiten Nos referimos al ahora famoso realizar operaciones. A da de hoy los XMLHttpRequest. ms importantes: Si vemos el cdigo del Listado 3, vere Manipulacin DOM mos un lenguaje que quiz nos recuerda Manipulacin XML a Java. En realidad no tienen absoluta XMLHTTP DOM permite a Javascript manipular, en Listado 4: fichero estilo.css tiempo real, el contenido de la pgina web. Puede aadir, modificar o quitar etiquetas y atributos, por lo que pode01 #documento{ mos operar sobre el documento de cual02 margin-left: quier forma posible. Javascript puede 100px; manipular un fichero XML de igual 03 } forma que hace DOM. 04 Y la gran novedad, Javascript puede 05 realizar conexiones ASNCRONAS con el 06 #titulo{ servidor. Y resalto en mayscula la pala07 text-decoration: bra ASNCRONAS porque ah est la underline; clave. 08 } Esto significa que podemos hace cone09 xiones, traernos documentos XML del 10 servidor y realizar operaciones DOM o 11 de cualquier otro tipo, cuando quera12 #linea0 { mos! 13 margin: 0px; El usuario carga su pgina web, y una 14 padding-left: 20px; vez cargada, sin necesidad de recargarla, 15 background: #e0e0e0; podemos modificarla a nuestro antojo en 16 font-family: monosbase a informacin que podemos pedir pace; al servidor en cualquier momento. 17 } Volviendo a nuestras funciones, la fun18 cin hazPeticion() recibe una url, crea el 19 #linea1 { objeto XMLHttpRequest y despus de 20 margin: 0px; algunas comprobaciones, asigna una 21 padding-left: 20px; funcin para que sea invocada cuando el 22 font-family: monosfichero que esa url especifica sea compace; pletamente descargado. 23 } Esto significa que mientras leemos 24 nuestra web, Javascript estar bajando 25 #contenedor{ un fichero y, cuando finalice, llamar a 26 border-style: la funcin modificaContenido . dashed; Y qu hace esta funcin? Comprueba 27 border-width: el estado de la peticin, (el estado 200 el 1px; de todo correcto y el de 404 el de lo 28 width: 600px; sentimos mucho, pero el fichero solicita29 border-color: do no est disponible) y entonces obtieblack; ne el documento XML del objeto que 30 } gestionaba la conexin.
Pero antes invoca a vaciaContenido(), que localiza toda etiqueta con las ids linea0 o linea1 y las elimina de la pgina. Hacemos esto porque a continuacin las volvemos a introducir en la pgina, pero esta vez con los datos frescos del servidor. No queremos entrar en los detalles, ya que, en teora, esto es un artculo sobre Python no Javascript, pero bsicamente esto es lo que hace el fichero ajax.js. El fichero estilo.c, que aparece en el listado 4, simplemente configura los colores y caractersticas de algunas de las etiquetas, para que el aspecto mejore. Y se acab, aqu tenemos nuestra aplicacin AJAX. El resultado final ser el que vemos en la figura 3. Cuando pulsemos cualquiera de los botones, se cargar la salida de texto de la ejecucin asociada a cada uno de ellos en pantalla, pero sin recargar la pgina. Si queremos aadir un nuevo comando slo tenemos que introducir la lnea correspondiente en acciones en server.py y aadir un nuevo botn como los que ya existen en index.html.
Conclusin
Es tan complicado eso de AJAX? Por supuesto que no! Lo que ocurre es que es una palabra que se est convirtiendo en un mito, pero no deja de ser una astuta combinacin de programacin en el servidor y cliente adems del uso intensivo de XMLHttpRequest. Poco a poco AJAX est poblando todas las pginas webs y la mayora de los currculos vitae. Quien sabe, lo mismo dentro de dos aos esa palabra tenga tanto poder como otra palabra de cuatro I letras: J2EE.
60
Nmero 12
WWW.LINUX- MAGAZINE.ES