Prácticas
Para las siguientes prácticas se indicarán los siguientes puntos a desarrollar por cada una:
- Cada práctica contará con su propio directorio ráiz:
$HOME/www/xhr0x
- Cada práctica contará con un nombre de host:
xhr0x.com
- Cada práctica contará con un puerto TCP:
808x
- En base al nombre de host se tendrá un URL:
http://xhr0x.com:808x
El servidor web a usar es
thttpd
:alumno@servidor:~ $ cd $HOME/www/xhr0x alumno@servidor:~ $ thttpd -D -p 808x -T UTF-8 -nor -l -
Para configurar el nombre de host tienes que asociar la dirección ip 127.0.0.1
a xhr0x.com
(según sea el caso)
en el archivo /etc/hosts
del sistema operativo.
Práctica 01
- Directorio ráiz:
$HOME/www/xhr01
. - Puerto TCP:
8081
- Nombre de host:
xhr01.com
- URL: http://xhr01.com:8081
Esta práctica plantea la descarga de un documento XML haciendo uso de XMLHttpRequest.
De http://www.sepomex.gob.mx/lservicios/servicios/CodigoPostal_Exportar.aspx descarga los códigos postales de algún estado en formato XML. Te recomiendo que trabajes con Baja California Sur ya que contiene menos cantidad de códigos postales.
Notas:
- En el caso de Baja California Sur el archivo que entrega el servidor solo tiene por nombre
Baja, descargalo y renombralo a
BajaCaliforniaSur.xml
. - En base al contenido de los archivos en formato XML, estos han sido generados desde Microsoft SQL Server mediante el uso de DataSets (ADO.NET).
- En el caso de Baja California Sur el archivo que entrega el servidor solo tiene por nombre
Baja, descargalo y renombralo a
Crea el directorio
xml
y en él deposita el archivo descargado en el anterior paso.Crea el archivo
index.html
con el siguiente contenido:<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>xhr01</title> <style> body { width: 960px; margin: 10px auto 30px auto; } #archivo_a_descargar { width: 100%; } #archivo_descargado { width: 100%; height: 200px; } #mensaje { color: red; } </style> </head> <body onload="iniciar();"> <h1>xhr01</h1> <form id="formulario"> <fieldset> <legend>Entidades</legend> <label for="archivo">Seleccione una entidad:</label> <select id="archivo_a_descargar"> <option value="Aguascalientes.xml">Aguascalientes</option> <option value="BajaCalifornia.xml">Baja California</option> <option value="BajaCaliforniaSur.xml">Baja California Sur</option> <option value=""></option> <option value="Oaxaca.xml">Oaxaca</option> <option value="EntidadQueNoExiste.xml">Entidad Que No Existe</option> <option value="Zacatecas.xml">Zacatecas</option> </select> <input type="button" value="Descargar" id="descargar" /> </fieldset> </form> <h1>Resultado:</h1> <p id="mensaje"></p> <textarea id="archivo_descargado"></textarea> <script src="js/xhr01a.js"></script> </body> </html>
Crea el directorio
js
y en él el archivoxhr01a.js
con el siguiente contenido:var descargar = function(evento) { var archivo_a_descargar = document.getElementById("archivo_a_descargar"); var archivo_descargado = document.getElementById("archivo_descargado"); var mensaje = document.getElementById("mensaje"); archivo_descargado.value = ""; mensaje.textContent = ""; if (! /^\w+\.xml$/.test(archivo_a_descargar.value)) { mensaje.textContent = "Seleccione una entidad."; return false; } var servidor = "http://xhr01.com:8081"; var url = servidor + "/xml/" + archivo_a_descargar.value + "?r=" + Math.random(); var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (this.readyState === 4) { var archivo_descargado = document.getElementById("archivo_descargado"); var mensaje = document.getElementById("mensaje"); archivo_descargado.value = ""; mensaje.textContent = ""; if (this.status === 200) { archivo_descargado.value = this.responseText; } else { mensaje.textContent = "Error " + this.status + " " + this.statusText + " - " + this.responseURL; } } }; xhr.open('GET', url, true); xhr.send(); }; var iniciar = function() { var boton_descargar = document.getElementById("descargar"); boton_descargar.addEventListener('click', descargar, false); };
Accede a http://xhr01.com:8081 y mientras tengas abierto a Console selecciona a Baja California Sur del formulario mostrado y da clic sobre el botón Descargar.
Descargua los códigos postales de los demás estado siguiendo la misma pauta dada para Baja California Sur, tomando
en cuenta de no usar letras acentuadas en el nombre de los archivos, y actualiza el elemento <select>
encontrado en el
archivo index.html
.
Al finalizar tendrás una estructura similar a:
alumno@servidor:~/www/xhr01 $ pwd && tree
/home/alumno/www/xhr01
.
├── index.html
├── js
│ └── xhr01a.js
└── xml
├── Aguascalientes.xml
├── BajaCaliforniaSur.xml
├── BajaCalifornia.xml
├── ...
├── VeracruzDeIgnacioDeLaLlave.xml
├── Yucatan.xml
└── Zacatecas.xml
2 directories, 34 files
Práctica 02
- Directorio ráiz:
$HOME/www/xhr02
. - Puerto TCP:
8082
- Nombre de host:
xhr02.com
- URL: http://xhr02.com:8082
Esta práctica plantea el recorrido de un documento XML así como acceder a su contenido y generar a partir de él una tabla
de HTML (<table>
).
Crea el archivo
index.html
el siguiente contenido:<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>xhr02</title> <style> body { width: 960px; margin: 10px auto 30px auto; } #archivo_a_descargar { width: 100%; } #archivo_descargado { width: 100%; height: 200px; } #mensaje { color: red; } #resultado { width: 100%; font-family: sans-serif; color: #000; font-size: 7px; background: #ccc; margin: 0; border: #aaa 1px solid; } #resultado tr { text-align: center; } #resultado th { border-top: 1px solid #fafafa; border-bottom:1px solid #e0e0e0; background: #ededed; text-align: center; } #resultado td { border-top: 1px solid #ffffff; border-bottom:1px solid #e0e0e0; border-left: 1px solid #e0e0e0; background: #fafafa; text-align: center; } #resultado tr.even td { background: #f6f6f6; } #resultado tr:hover td { background: #f2f2f2; } </style> </head> <body onload="iniciar();"> <h1>xhr02</h1> <form id="formulario"> <fieldset> <legend>Entidades</legend> <label for="archivo">Seleccione una entidad:</label> <select id="archivo_a_descargar"> <option value="Aguascalientes.xml">Aguascalientes</option> <option value="BajaCalifornia.xml">Baja California</option> <option value=""></option> <option value="EntidadQueNoExiste.xml">Entidad Que No Existe</option> <option value="BajaCaliforniaSur.xml">Baja California Sur</option> <option value=""></option> <option value="Zacatecas.xml">Zacatecas</option> </select> <input type="button" value="Descargar" id="descargar" /> </fieldset> </form> <h1>Resultado: <span id="cantidad_de_codigos_postales"></span></h1> <p id="mensaje"></p> <table id="resultado"><thead></thead><tbody></tbody></table> <script src="js/xhr02a.js"></script> </body> </html>
Crea el archivo
js/xhr02a.js
con el siguiente contenido:var actualizarTabla = function(documento_xml) { /* Para acceder al DOM de documento_xml en Console: */ console.log("Documento: " + documento_xml.URL); console.log(documento_xml); /* Eliminación de thead y tbody de table */ var tabla = document.getElementById("resultado"); if (tabla.firstChild && tabla.lastChild) { tabla.removeChild(tabla.firstChild); tabla.removeChild(tabla.lastChild); } /* Cabecera (<thead>) de la tabla * El siguiente documento PDF indica los campos que conforman la información * por cada estado: * http://www.correosdemexico.gob.mx/lservicios/servicios/imagenes%5CDescrip.pdf */ var campos = []; var xml_campos_primer_estado = documento_xml.firstChild.childNodes[1].childNodes; var tabla_thead = document.createElement("thead"); tabla.appendChild(tabla_thead); var tabla_tr = document.createElement("tr"); tabla_thead.appendChild(tabla_tr); var tabla_th = document.createElement("th"); tabla_th.textContent = "#"; tabla_tr.appendChild(tabla_th); for (var i = 0; i < xml_campos_primer_estado.length; i++ ) { var tabla_th = document.createElement("th"); tabla_th.textContent = xml_campos_primer_estado[i].nodeName; tabla_tr.appendChild(tabla_th); campos.push(xml_campos_primer_estado[i].nodeName); } /* Cuerpo (<tbody>) de la tabla */ var xml_nodos = documento_xml.firstChild.childNodes; var tabla_tbody = document.createElement("tbody"); tabla.appendChild(tabla_tbody); for (var i = 1; i < xml_nodos.length; i++) { /* Contador */ var tabla_tr = document.createElement("tr"); var tabla_contador = document.createElement("td"); tabla_contador.textContent = i; tabla_tr.appendChild(tabla_contador); /* Campos por estado */ var nodo_elemento = xml_nodos[i].childNodes; for (var j=0; j < campos.length; j++) { var tabla_td = document.createElement("td"); if (nodo_elemento[j] && campos[j] === nodo_elemento[j].nodeName) { tabla_td.textContent = nodo_elemento[j].textContent; } else { /* Si el estado no cuenta con este campo */ tabla_td.textContent = "N/A"; } tabla_tr.appendChild(tabla_td); } tabla_tbody.appendChild(tabla_tr); } var cantidad_de_codigos_postales = document.getElementById("cantidad_de_codigos_postales"); cantidad_de_codigos_postales.textContent = (i - 1) + " códigos postales"; } var descargar = function(evento) { var archivo_a_descargar = document.getElementById("archivo_a_descargar"); var mensaje = document.getElementById("mensaje"); var cantidad_de_codigos_postales = document.getElementById("cantidad_de_codigos_postales"); var tabla = document.getElementById("resultado"); mensaje.textContent = ""; cantidad_de_codigos_postales.textContent = ""; /* Eliminación de thead y tbody de table */ if (tabla.firstChild && tabla.lastChild) { tabla.removeChild(tabla.firstChild); tabla.removeChild(tabla.lastChild); } if (! /^\w+\.xml$/.test(archivo_a_descargar.value)) { mensaje.textContent = "Seleccione una entidad."; return false; } var servidor = "http://xhr02.com:8082"; var url = servidor + "/xml/" + archivo_a_descargar.value + "?r=" + Math.random(); var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (this.readyState === 4) { var mensaje = document.getElementById("mensaje"); var cantidad_de_codigos_postales = document.getElementById("cantidad_de_codigos_postales"); mensaje.textContent = ""; cantidad_de_codigos_postales.textContent = ""; if (this.status === 200) { actualizarTabla(xhr.responseXML); } else { mensaje.textContent = "Error " + this.status + " " + this.statusText + " - " + this.responseURL; } } }; xhr.open('GET', url, true); xhr.send(); }; var iniciar = function() { var boton_descargar = document.getElementById("descargar"); boton_descargar.addEventListener('click', descargar, false); };
Crea el directorio
xml
y deposita en él todos los archivos xml con los códigos postales obtenidos en la anterior práctica. Actualiza el archivoindex.html
de igual forma.Accede a http://xhr02.com:8082 y realiza lo mismo que en la práctica anterior.
Práctica 03
- Directorio ráiz:
$HOME/www/xhr03
. - Puerto TCP:
8083
- Nombre de host:
xhr03.com
- URL: http://xhr01.com:8083
Sobre el envío de datos al servidor mediante el objeto XMLHttpRequest
y los métodos GET y POST de HTTP.
El uso de Python en el lado del servidor es solo para demostración de la recepción de los datos capturados en el formulario de HTML usando al objeto XMLHttpRequest, pero además del como el objeto XMLHttpReques puede hacer algo con los datos recibidos del servidor. Es posible tener cualquier otro lenguaje de programación en el lado del servidor.
Crea el archivo
index.html
con el siguiente contenido:<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>xhr03</title> <style> body { width: 960px; margin: 10px auto 30px auto; } #archivo_a_descargar { width: 100%; } #respuesta { width: 100%; background-color: #f2f2f2; } #mensaje { color: red; } </style> </head> <body onload="App.main();"> <h1>xhr03</h1> <form id="formulario"> <fieldset> <legend>Formulario</legend> <p> <label for="nombre">Nombre:</label> <input type="text" id="nombre" /> </p> <p> <label for="nacimiento">Año de nacimiento:</label> <input type="text" id="nacimiento" /> </p> <p> <label for="metodo_http">Método HTTP:</label> <select id="metodo_http"> <option value="GET">GET</option> <option value="POST">POST</option> </select> </p> <p> <input type="button" value="Enviar" id="descargar" /> </p> </fieldset> </form> <h1>Resultado:</h1> <pre id="respuesta"></pre> <p id="mensaje"></p> <script src="js/xhr03a.js"></script> </body> </html>
Crea el archivo
js/xhr03a.js
con el siguiente contenido:var App = ( function() { var _descargar = function(evento) { var url = "http://xhr03.com:8083/cgi-bin"; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = _procesarCambioDeEstado(xhr); var parametros = "nombre=" + document.getElementById("nombre").value + "&" + "nacimiento=" + document.getElementById("nacimiento").value; if (document.getElementById("metodo_http").value === "GET") { xhr.open('GET', url + "/get.py" + "?" + parametros); xhr.send(); } else { xhr.open('POST', url + "/post.py"); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.setRequestHeader("Content-Length", parametros.length); xhr.setRequestHeader("Connection", "close"); xhr.send(parametros); } } var _procesarCambioDeEstado = function(objeto_XMLHttpRequest) { return function() { var respuesta = document.getElementById("respuesta"); var mensaje = document.getElementById("mensaje"); respuesta.textContent = ""; mensaje.textContent = ""; if (objeto_XMLHttpRequest.readyState === 4) { if (objeto_XMLHttpRequest.status === 200) { respuesta.textContent = objeto_XMLHttpRequest.responseText; } else { mensaje.textContent = "Error " + this.status + " " + this.statusText + " - " + this.responseURL; } } }; } var _main = function() { var boton_descargar = document.getElementById("descargar"); boton_descargar.addEventListener('click', _descargar, false); } return { "main": _main }; } )();
Crea el archivo
servidor.py
con el siguiente contenido:#!/usr/bin/env python3 import http.server puerto = 8083 servidor = http.server.HTTPServer(("", puerto), http.server.CGIHTTPRequestHandler) try: print("Atendiendo solicitudes en ", puerto) servidor.serve_forever() except KeyboardInterrupt: print("Deteniendo servidor...") servidor.socket.close()
Crea el directorio
cgi-bin
y en él los archivosget.py
ypost.py
con el siguiente contenido en ambos casos:#!/usr/bin/env python3 import os, cgi solicitud = cgi.FieldStorage() agente_de_usuario = os.environ["HTTP_USER_AGENT"] referencia_http = os.environ["HTTP_REFERER"] archivo_cgi = os.environ["SCRIPT_NAME"] nombre = "" nacimiento = "" if "nombre" in solicitud: nombre = solicitud["nombre"].value if "nacimiento" in solicitud: nacimiento = solicitud["nacimiento"].value print("Content-Type: text/plain") print("") print("Servidor:", referencia_http) print("Script:", archivo_cgi) print("Agente de usuario:", agente_de_usuario) print("") print("nombre =", nombre) print("nacimiento =", nacimiento)
Asigna permisos de ejecución a los archivos
cgi-bin/get.py
ycgi-bin/post.py
:alumno@servidor:~/www/xhr03 $ chmod +x cgi-bin/get.py cgi-bin/post.py
Hasta este punto tendrás la siguiente estructura en
$HOME/www/xhr03
:alumno@servidor:~/www/xhr03 $ pwd && tree /home/alumno/www/xhr03 . ├── cgi-bin │ ├── get.py │ └── post.py ├── index.html ├── js │ └── xhr03a.js └── servidor.py 2 directories, 5 files
Inicia el servidor web haciendo uso de Python:
alumno@servidor:~/www/xhr03 $ python3 servidor.py
Accede a http://xhr03.com:8083, rellena el formulario, selecciona alguna de las opciones de Método HTTP, da clic al botón Enviar y revisa el documento HTML obtenido desde el servidor.
Observaciones:
- El formulario en
index.html
no define sus atributosmethod
yaction
. - Podrías generar un documento XML de forma dinámica desde el lado del servidor y solicitar dicho documento desde el lado del cliente. En el lado del cliente (Navegador Web + JavaScript + DOM + XMLHttpRequest) crear una Interfaz Gráfica de Usuario que interactue con el lado del servidor.