L7: Práctica 3 1 - myTeachingURJC/2018-19-LTAW GitHub Wiki

Sesión Laboratorio 7: Práctica 3-1

  • Tiempo: 2h
  • Fecha: Lunes, 11-Marzo-2019
  • Objetivos de la sesión:
    • Explicar el enunciado de la práctica 3
    • Aprender a usar las cookies en node.js
    • Aprender a crear formularios en html
    • Recibir la información en nuestro servidor node.js

Contenido

Enunciado Práctica 3

El objetivo de la práctica es familiarizarse con tres formas de interacción entre un cliente y un servidor: Formularios, cookies y peticiones AJAX. Con ellos implementaremos tres nuevas características a nuestro servidor web tienda de la práctica 1: Formulario de compra, carrito de la compra y búsqueda con autocompletado

  • Carrito de la compra: Para tener carrito de la compra, el usuario deberá registrarse primero en la tienda. Para ello pinchará en el enlace en ingresar y el servidor creará una cookie con un identificador de usuario creado al azar. En cada producto habrá un botón de añadir al carrito, que hará que el servidor añada el producto a otra cookie. Al apretar el botón de comprar, el servidor leerá los productos a comprar de la cookie, y los mostrará como respuesta

  • Formulario de compra: Al pinchar en el enlace de comprar, además de lo anterior, el servidor enviará un formulario donde el usuario deberá rellenar los datos para formalizar la compra: Nombre, Apellidos, Correo Electrónico y Método de pago (paypal, tarjeta de crédito, transferencia bancaria). El servidor recibe esta información y debe crear una página de respuesta, mostrando los datos recibidos

  • Búsqueda con autocompletado: La tienda tendrá una caja de búsqueda, para buscar información sobre un producto. Al escribir 3 ó más caracteres, aparecerá un menú desplegable con las opciones posibles. Al apretar el botón de buscar se enviará esta inforamción, y el servidor devolverá una página con información sobre el producto

Se implementará en Node.js, partiendo del código de la práctica 1

Actividades guiadas

Actividades guiadas por el profesor. Haremos lo siguiente:

Manejando cookies

Las Cookies son datos que envían los servidores web y que se almacenan en el navegador. De esta forma el servidor puede recordar a un usuario que se haya conectado previamente y retomar su sesión

Las cookies son cadenas de texto compuestas por caracteres ASCII imprimibles, de la forma: nombre=valor. Ni el nombre ni el valor pueden contener espacios ni los caracteres coma (,) ni punto y coma (;). El carácter ; se usa para separar pares. Así por ejemplo, podemos tener una cookie como la siguiente: "nombre1=valor1; nombre2=valor2"

Para establecer el valor de una Cookie hay que usar el encabezado Set-Cookie en el mensaje de respuesta del servidor. Desde node.js lo hacemos usando el método setHeader de la biblioteca http

Ejemplo 1: Estableciendo una cokie. Leyendo su valor

Este es un ejemplo completo para comprobar el funcionamiento. Cópialo en el fichero cookie-1.js. Lo iremos probando y explicando su funcionamiento

var http = require('http');
var url = require('url');

const PORT = 8080

console.log("Arrancando servidor en puerto " + PORT)

//-- Configurar y lanzar el servidor. Por cada peticion recibida
//-- se imprime un mensaje en la consola
http.createServer((req, res) => {

  //-- Mostrar en la consola el recurso al que se accede
  var q = url.parse(req.url, true);
  console.log("Petición: " + q.pathname)

  //-- Leer las cookies
  var cookie = req.headers.cookie;
  console.log("Cookie: " + cookie)

  //-- Segun el recurso al que se accede
  switch (q.pathname) {

    //-- Pagina principal
    case "/":
      content = "Bienvenido a mi tienda "

      //-- No hay ninguna cookie
      if (!cookie) {
        content += "\nNo te conozco... Registrate!\n"
        content += "Accede a /login"

      //-- Hay definida una Cookie.
      } else {
        content += "Obijuan"
      }

      res.statusCode = 200;
      break;

    //-- Pagina de acceso
    case "/login":
      content = "Registrado! Cookie enviada al navegador!"

      //-- ESTABLECER LA COOKIE!!
      res.setHeader('Set-Cookie', 'user=obijuan')
      break

    //-- Se intenta acceder a un recurso que no existe
    default:
      content = "Error";
      res.statusCode = 404;
  }


  //-- Generar el mensaje de respuesta
  res.setHeader('Content-Type', 'text/plain')
  res.write(content);
  res.end();

}).listen(PORT);

Lazamos este servidor

$ node cookie-1.js 
Arrancando servidor en puerto 8080

Accedemos a la página principal desde el navegador: http://localhost:8000

En la consola donde hemos lanzado el servidor veremos:

$ node cookie-1.js 
Arrancando servidor en puerto 8080
Petición: /
Cookie: undefined

El servidor ha recibido una petición del recurso "/", y no se ha recibido ninguna cookie, por lo que el servidor no sabe quién es el usuario que ha realizado la petición

Ya conocemos la mayor parte del funcionamiento del servidor. Cada vez que se recibe una petición se ejecuta la función definida en createServer. Como parámetros se le pasa el mensaje de solicitud req, y el mensaje de respuesta res (vacío)

Primero se obiene el recurso pedido, que se encuentra en q.pathname

//-- Mostrar en la consola el recurso al que se accede
  var q = url.parse(req.url, true);
  console.log("Petición: " + q.pathname)

Luego se obtienen las cookies enviadas por el navegador, que están en el objeto req.headers.cookie

//-- Leer las cookies
  var cookie = req.headers.cookie;
  console.log("Cookie: " + cookie)

Como el navegador no tiene ninguna cookie todavía, en la consola vemos undefined. A continuación el servidor procesa el recurso solicitado. En este caso se pide la página principal, por lo que la parte de código que se ejecutará es:

//-- Pagina principal
    case "/":
      content = "Bienvenido a mi tienda "

      //-- No hay ninguna cookie
      if (!cookie) {
        content += "\nNo te conozco... Regístrate!\n"
        content += "Accede a /login"

      //-- Hay definida una Cookie.
      } else {
        content += "Obijuan"
      }

      res.statusCode = 200;
      break;

Como no hay cookie definidas, el mensaje de respuesta generado es: "No te conozco... Regístrate. Accede a /login". Nos indica que accedamos al recurso /login para proceder al registro. Lo suyo sería haber enviado una paǵina html como un link, pero para que el ejemplo ocupe poco se han utilizamo mensajes de texto y hay que introducir los recursos a mano

Ahora accedemos a http://localhost/8080:/login desde el navegador

En la consola veremos un nuevo mensaje indicando que hemos accedido a /login, y el navegador no ha enviado ninguna cokie todavía

$ node cookie-1.js 
Arrancando servidor en puerto 8080
Petición: /
Cookie: undefined
Petición: /login
Cookie: undefined

En el navegador nos aparecerá lo siguiente:

Al acceder a este recurso, el servidor ha ejecutado el siguiente código:

//-- Pagina de acceso
    case "/login":
      content = "Registrado! Cookie enviada al navegador!"

      //-- ESTABLECER LA COOKIE!!
      res.setHeader('Set-Cookie', 'user=obijuan')
      break

Ahora se crea la cookie user con el valor obijuan, que se envía al navegador en el mensaje de respuesta

Si ahora accedemos de nuevo a la página principal, el navegador enviará en el mensaje de solitud la cookie recibida (a partir de ahora la enviará en TODAS las solicitudes). El servidor detecta la cookie y envía un mensaje diferente. En este caso envía un mensaje personalizado

Y en la consola veremos este nuevo mensaje:

$ node cookie-1.js 
Arrancando servidor en puerto 8080
Petición: /
Cookie: undefined
Petición: /login
Cookie: undefined
Petición: /
Cookie: user=obijuan

Desde el navegador podemos ver las cookies que se envían en el mensaje de solicitud. Para ello nos vamos la opción web developer/network. Recargamos la página para generar una nueva petición y pinchamos en la primera petición. Veremos lo siguiente:

En la parte inferior vemos la cookie: user=obijuan

Podemos ver todas las cookies de ese dominio accediendo a web developer/Storage:

Vemos que esta cookie expira al terminar la sesión con el navegador. Si cerramos el navegador y lo volvemos a abrir, esta cookie la habremos perdido

Para hacer pruebas, también podemos borrar las cookies desde preferences/privacy & security/Cookies and Site Data/Manage data. Ahí buscamos localhost. Lo seleccionamos y pinchamos en remove selected

Formularios

Los formularios contienen elementos html para que el usuario introduzca datos: campos de texto, campos numéricos, botones de selección, etc. Se puede encontrar mucha información en este tutorial del w3school

Todos los elementos de entrada del formulario se sitúan entre las etiquetas <form> y </form>. Con el atributo atributo action definimos el recurso al que acceder en el servidor al apretarse el botón de envío. Con el atributo method definimos la manera de enviar esos datos al servidor: bien usando GET o bien con POST. Nosotros usaremos POST

Con el método GET se envía un mensaje de solicitud estándar, sin cuerpo, y los valores del formulario se pasan como parámetros en el recurso de acceso (Ej. /solicitud?Nombre=trollface). Con el método POST los datos se envían en el cuerpo del mensaje. Esto permite que con POST se puedan enviar muchísimos más datos que con GET (incluso ficheros)

Formulario hola mundo

Para practicar usaremos un formulario muy simple, que sólo tiene un campo de texto y un botón de envío. El fichero HTML es el siguiente:

<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="utf-8">
    <title>FORM 1</title>
  </head>
  <body>
    <form action="/myform" method="post">
      Nombre:
      <input type="text" name="Nombre"/> <br />
      <input type="submit" value="Enviar"/>
    </form>
  </body>
</html>

Si vemos la página desde el navegador (o con el previsualizador del Atom), nos saldrá esto:

Las entradas se crean mediante la etiqueta <input>. Con el atributo type se define el tipo de entrada. En este caso estamos colocando dos entradas. Una es de tipo texto (text), y la otra es el botón de envía (submit). Con el atributo name establecemos el nombre de la entrada, y será lo que el formulario enviará. En este caso enviará la cadena "Nombre=lo introducido por el usuario"

En el caso del botón de enviar, el atributo value determina el texto que aparecerá sobre el botón

Ejemplo 2: Recibiendo datos en el servidor

Usaremos el formulario Hola mundo para enviar una cadena de texto al servidor. El servidor leerá el texto recibido y generará un mensaje de respuesta con la cadena recibida (sin procesar). Simplemente para ver cómo los datos han viajado del cliente al servidor, y de vuelta al cliente

En vez de leer el formulario del fichero .html, lo incluimos directamente en una variable en node (por simplicidad del ejemplo). El ejemplo en node.js es este:

var http = require('http');
var url = require('url');

const PORT = 8080

console.log("Arrancando servidor en puerto " + PORT)

//-- Configurar y lanzar el servidor. Por cada peticion recibida
//-- se imprime un mensaje en la consola
http.createServer((req, res) => {

  //-- Mostrar en la consola el recurso al que se accede
  var q = url.parse(req.url, true);
  console.log("Petición: " + q.pathname)

  //-- Segun el recurso al que se accede
  switch (q.pathname) {

    //-- Pagina principal
    case "/":
      content = "Bienvenido a mi tienda "

      content = `
        <!DOCTYPE html>
        <html lang="es">
          <head>
            <meta charset="utf-8">
            <title>FORM 1</title>
          </head>
          <body>
            <form action="/myform" method="post">
              Nombre:
              <input type="text" name="Nombre"/> <br />
              <input type="submit"/>
            </form>
          </body>
        </html>
      `

      res.statusCode = 200;
      break;

    //-- Pagina de acceso
    case "/myform":

      if (req.method === 'POST') {
        // Handle post info...

        var content = `
        <!DOCTYPE html>
        <html lang="es">
          <head>
            <meta charset="utf-8">
            <title>FORM 1</title>
          </head>
          <body>
            <p>Recibido: `

        req.on('data', chunk => {
            //-- Leer los datos (convertir el buffer a cadena)
            data = chunk.toString();

            //-- Añadir los datos a la respuesta
            content += data;

            //-- Fin del mensaje. Enlace al formulario
            content += `
                </p>
                <a href="/">[Formulario]</a>
              </body>
            </html>
            `
            //-- Mostrar los datos en la consola del servidor
            console.log("Datos recibidos: " + data)
            res.statusCode = 200;
         });

         req.on('end', ()=> {
           //-- Generar el mensaje de respuesta
           res.setHeader('Content-Type', 'text/html')
           res.write(content);
           res.end();
         })
         return
      }

      break

    //-- Se intenta acceder a un recurso que no existe
    default:
      content = "Error";
      res.statusCode = 404;
  }

  //-- Generar el mensaje de respuesta
  res.setHeader('Content-Type', 'text/html')
  res.write(content);
  res.end();

}).listen(PORT);

Arrancamos el servidor y lanzamos la petición de la página principal. En la consola nos aparecerá lo siguiente:

$ node form-1.js 
Arrancando servidor en puerto 8080
Petición: /

Y en el navegador veremos la página del formulario:

Introducimos un valor (por ejemplo Testing...) y pinchamos en el botón de Enviar. El navegador cambiará a URL http://localhost:8080/myform. En la consola veremos este mensaje:

$ node form-1.js 
Arrancando servidor en puerto 8080
Petición: /
Petición: /myform
Datos recibidos: Nombre=Testing...

La cadena que se ha recibido del servidor es Nombre=Testing, donde Nombre es el texto que hemos puesto en el atributo name de la entrada de texto, y Testing... es el texto que hemos introducido

En el navegador vemos la página HTML con la respuesta, donde también aparece la cadena recibida: Nombre=Testing. Es responsabilidad del servidor analizar la cadena recibida (parsing) y separarla en sus campos. En este ejemplo NO se ha hecho

En esta animación se muestra su funcionamiento

Analicemos el código. Cuando se realiza la petició de la página principal (/) se genera una página html al vuelo, con el formulario "hola mundo"

Cuando el usuario ha rellenado la entrada de texto y pulsado en el botón de envío, se invoca el recurso /myform. En el código se comprueba primero que se ha recibido una solicitud de tipo POST:

    case "/myform":

      if (req.method === 'POST') {
        // ...

En la variable content se sitúa la primera parte del HTML de respuesta a enviar. Para leer la información recibida en el cuerpo, se usa este código:

    req.on('data', chunk => {
        //-- Leer los datos (convertir el buffer a cadena)
        data = chunk.toString();

        //-- Añadir los datos a la respuesta
        content += data;

        //-- Fin del mensaje. Enlace al formulario
        content += `
            </p>
              <a href="/">[Formulario]</a>
              </body>
          </html>
            `
        //-- Mostrar los datos en la consola del servidor
        console.log("Datos recibidos: " + data)
        res.statusCode = 200;
     });

Javascript es un lenguaje orientado a eventos. Con la instrucción req.on() se está estableciendo la función de retrollamada para el evento de llegada de datos en el cuerpo, y se le pasa como parámetro el buffer con los datos. Estos datos se convierten a tipo cadena y se insertan en la variable con el HTML

Mediante req.on('end', ...) generamos el mensaje de respuesta, una vez que se ha terminado de procesar el mensaje de solicitud

Actividades NO guiadas

Con los ejemplos que hemos visto en esta sesión ya puedes hacer las dos primeras partes de la práctica: El carrito de la compra y el formulario de compra

  • Comienza haciendo un sistema de registro: El usuario debe pinchar en un enlace para acceder. Esto se podría hacer también con formularios (enviando el login y password). Sin embargo lo haremos como en el ejemplo 1: Simplemente generando una cookie aleatoria, para simplificar

  • Implementa el carrito de la compra. Cada vez que se pulse el botón de añadir un producto al carrito, se generará una cookie en la que se añade el producto

  • Implementa el formulario de compra. Al acceder a la página, el servidor sabrá los productos que se quieren comprar porque tiene acceso al carrito. Al enviar los datos del formulario el servidor generará una página indicando todo lo que se ha comprado y confirando los datos recibidos

Autores

Licencia

Enlaces

⚠️ **GitHub.com Fallback** ⚠️