Skip to content

S6: Formularios y Cookies

Juan Gonzalez-Gomez edited this page Mar 14, 2022 · 6 revisions

Sesión 6: Formularios y Cookies

  • Tiempo: 2h (50 + 50min)
  • Fecha:
  • Objetivos de la sesión:
    • Aprender el funcionamiento de los formularios web
    • Entender las Cookies y su implementación
    • Ejemplos de implementación de formularios y cookies en node.js

Contenido

Introducción

Estudiaremos dos mecanismos de intercambio de información entre el cliente y el servidor: formularios y cookies. Con los formularios el cliente envía información al servidor a través de los parámetros de la URL o bien en el cuerpo del mensaje. Con las Cookies el intercambio de información se hace en las cabeceras

Intercambio de datos entre cliente y servidor

Repasemos los mecanismos de interecambio de datos entre el cliente y servidor. Lo realizan a través de los mensajes del protocolo HTTP. Recordemos que hay dos: mensajes de respuesta y mensajes de solicitud. Ambos mensajes tiene una línea de comienzo, cabeceras y cuerpo

Los datos del cliente al servidor se envían de tres formas diferentes:

Los datos del servidor al cliente se reciben de dos formas:

  • A través del cuerpo
  • A través de las cabeceras

Mediante los formularios web, el cliente envía información al servidor mediante los métodos GET o POST. Y por tanto, los datos van bien en los parámetros de la URL o bien en el cuerpo

Mediante las Cookies, cliente y servidor intercambian información en ambos sentidos, a través de las cabeceras

Formularios web

Los formularios Web son elementos HTML que permiten organizar la entrada de datos para el usuario y definir cómo se enviarán estos datos al servidor: qué método usar (Get o Post), a qué recurso del servidor acceder, qué nombres dar a los datos enviados...

URLs asociadas a los formularios

Con los formularios hay dos URLs implicadas:

  • La URL del formulario: Es donde se encuentra el fichero html con el formulario
  • La URL de procesamiento de datos: Es la URL a la que enviar los datos al servidor

En este dibujo se muestra un ejemplo de funcionamiento. Supongamos que un usuario está en la página de una tienda. En un momento determinado ve un prodcuto que quiere comprar. Pincha en el botón de comprar. Esto es un enlace a la URL del formulario: una página web donde está el formulario para que introduzca los datos para formalizar la compra

El usuario introduce los datos en las casillas del formulario que aparecen en la página y aprieta el botón de enviar. El navegador realiza una petición al servidor en la URL de procesamiento de datos. El servidor recibe los datos, los procesa y genera una página web de respuesta con el resultado

Formulario hola mundo

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

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Formulario</title>
</head>
<body>
    <form action="/procesar" method="get">
        Nombre:
        <input type="text" name="nombre"/>
        <p></p>
        Apellidos:
        <input type="text" name="apellidos" />
        <p></p>
          <input type="submit" value="Enviar"/>
    </form>
</body>
</html>

Si vemos la página desde el navegador 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 tres entradas. Dos son de tipo texto (text), el Nombre y los Apellidos, y la otra es el botón de envíar (submit). Con el atributo name establecemos el nombre de la entrada, y será lo que el formulario enviará. En este formulario las dos entradas de texto se llaman nombre y apellidos

En el caso del botón de enviar, el atributo value determina el texto que aparecerá sobre el botón. Cuando se pulse este botón, el navegador generará una petición de tipo GET en el recurso /procesar del servidor. Esto se ha especificado en los atributios method y action del formulario

Ejemplo 1: Recibiendo datos en el servidor

Usaremos el formulario Hola mundo para enviar el nombre y los apellidos introducidos por el usuario al servidor. El servidor responderá devolviendo una página estática de confirmación de los datos

Este es el código del servidor de ejemplo. Sus dos páginas web asociadas son:

  • URL del formulario: / (raiz). El HTML se encuentra en el fichero form1.html (formulario "Hola mundo*)
  • URL del procesamiento: /procesar. El HTML se encuentra en el fichero form1-resp.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ejemplo 1</title>
</head>
<body>
    <h1>¡Datos Recibidos!</h1>
    <p>Gracias por su compra</p>
    <a href="/">Acceso al formulario</a>
</body>
</html>

Para hacer más sencillo el ejemplo, antes de arrancar el servidor ambas páginas web se cargan desde fichero y se almacenan en las variables FORMULARIO y RESPUESTA. Cada vez que se recibe una peticion se imprime en la consola la información sobre el método, la ruta y los parámetros

//-- Imprimir información sobre la solicitud recibida

const http = require('http');
const fs = require('fs');
const PUERTO = 8080;

//-- Cargar pagina web del formulario
const FORMULARIO = fs.readFileSync('form1.html','utf-8');

//-- HTML de la página de respuesta
const RESPUESTA = fs.readFileSync('form1-resp.html', 'utf-8');

//-- SERVIDOR: Bucle principal de atención a clientes
const server = http.createServer((req, res) => {

  //-- Construir el objeto url con la url de la solicitud
  const myURL = new URL(req.url, 'http://' + req.headers['host']);  
  console.log("");
  console.log("Método: " + req.method);
  console.log("Recurso: " + req.url);
  console.log("  Ruta: " + myURL.pathname);
  console.log("  Parametros: " + myURL.searchParams);

  //-- Por defecto entregar formulario
  let content_type = "text/html";
  let content = FORMULARIO;

  if (myURL.pathname == '/procesar') {
      content_type = "text/html";
      content = RESPUESTA;
  }

  //-- Si hay datos en el cuerpo, se imprimen
  req.on('data', (cuerpo) => {

    //-- Los datos del cuerpo son caracteres
    req.setEncoding('utf8');
    console.log(`Cuerpo (${cuerpo.length} bytes)`)
    console.log(` ${cuerpo}`);
  });

  //-- Esto solo se ejecuta cuando llega el final del mensaje de solicitud
  req.on('end', ()=> {
    //-- Generar respuesta
    res.setHeader('Content-Type', content_type);
    res.write(content);
    res.end()
  });

});

server.listen(PUERTO);
console.log("Escuchando en puerto: " + PUERTO);

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

$ node print-req.js 
Escuchando en puerto: 8080

Método: GET
Recurso: /
  Ruta: /
  Parametros:

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

Introducimos datos en los campos. Por ejemplo Nombre: Chuck y Apellidos: Norris y pinchamos en el botón de Enviar. El navegador cambiará a URL http://localhost:8080/procesar. En la consola veremos este mensaje:

$ node Ej-01.js 
Escuchando en puerto: 8080

Método: GET
Recurso: /
  Ruta: /
  Parametros: 

Método: GET
Recurso: /procesar?nombre=Chuck&apellidos=Norris
  Ruta: /procesar
  Parametros: nombre=Chuck&apellidos=Norris

Y en el navegador veremos la página web de respuesta:

El recurso al que se accede desde el navegador es:

/procesar?nombre=Chuck&apellidos=Norris

Se le están pasando los parámetros nombre y apellidos con los valores Chuck y Norris respectivamente

En esta animación se muestra su funcionamiento

Ejemplo 2: Probando el método POST

Vamos a probar lo mismo pero con el método POST. La página web del formulario es la misma, pero ahora se usa el atributo method="post". El fichero del formulario es este (form2.html):

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Formulario</title>
</head>
<body>
    <form action="/procesar" method="post">
        Nombre:
        <input type="text" name="nombre"/>
        <p></p>
        Apellidos:
        <input type="text" name="apellidos" />
        <p></p>
          <input type="submit" value="Enviar"/>
    </form>
</body>
</html>

El fichero javascript es igual, pero cambiamos el nombre del fichero form1.html por form2.html. Ahora, al enviar los datos desde el formulario llegan en el cuerpo del mensaje (en lugar de en la URL). En la consola veremos:

$ node Ej-02.js 
Escuchando en puerto: 8080

Método: GET
Recurso: /
  Ruta: /
  Parametros: 

Método: POST
Recurso: /procesar
  Ruta: /procesar
  Parametros: 
Cuerpo (29 bytes)
 nombre=Chuck&apellidos=Norris

Primero hay una petición GET de la URL del formulario. Luego hay una petición POST con la URL de procesamiento. Ahora no hay parámetros. Pero en el cuerpo podemos ver la información enviada: nombre=Chuck&apellidos=Norris

Ejemplo 3: Procesando los datos recibidos

En este ejemplo procesamos los datos recibidos. Tanto el nombre como el apellido que se han enviado con el formulario se añaden a la página de respuesta. Además, si el usuario es Chuck Norris, se añade un mensaje adicional en la respuesta

El nombre y apellidos recibidos se obtienen ejecutando estos métodos:

//-- Leer los parámetros
  let nombre = myURL.searchParams.get('nombre');
  let apellidos = myURL.searchParams.get('apellidos');

En las peticiones en las que no se incluyan estos parámetros, su valor será null

Para la página de respuesta, que está en el fichero form1-resp2.html, se utiliza una plantilla. Es una página HTML normal que tiene definidos unos nombres especiales: NOMBRE, APELLIDOS y HTML_EXTRA:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ejemplo 3</title>
</head>
<body>
    <h1>¡Datos Recibidos!</h1>
    <p>Gracias por su compra</p>
    <p>Nombre: NOMBRE</p>
    <P>Apellidos: APELLIDOS</P>
    HTML_EXTRA
    <p></p>
    <a href="/">Acceso al formulario</a>
</body>
</html>

Desde el código javascript se sustituyen estos nombres por su correspondientes valores utilizando el método replace

El código completo es el siguiente:

const server = http.createServer((req, res) => {

  //-- Construir el objeto url con la url de la solicitud
  const myURL = new URL(req.url, 'http://' + req.headers['host']);  

  //-- Leer los parámetros
  let nombre = myURL.searchParams.get('nombre');
  let apellidos = myURL.searchParams.get('apellidos');
  console.log(" Nombre: " + nombre);
  console.log(" Apellidos: " + apellidos);
  

  //-- Por defecto entregar formulario
  let content_type = "text/html";
  let content = FORMULARIO;

  if (myURL.pathname == '/procesar') {
      content_type = "text/html";

      //-- Reemplazar las palabras claves por su valores
      //-- en la plantilla HTML
      content = RESPUESTA.replace("NOMBRE", nombre);
      content = content.replace("APELLIDOS", apellidos);

      //-- si el usuario es Chuck Norris se añade HTML extra
      let html_extra = "";
      if (nombre=="Chuck" && apellidos=="Norris") {
         html_extra = "<h2>Chuck Norris no necesita registrarse</h2>";
      }
      content = content.replace("HTML_EXTRA", html_extra);
  }

  //-- Enviar la respuesta
  res.setHeader('Content-Type', content_type);
  res.write(content);
  res.end()

});

server.listen(PUERTO);
console.log("Escuchando en puerto: " + PUERTO);

Arrancamos el ejemplo. Primero se accede a la URL del formulario, por lo que los parámetros leidos están a null

$ node Ej-03.js 
Escuchando en puerto: 8080
 Nombre: null
 Apellidos: null

En el formulario introducimos un nombre. Por ejemplo Darth Vader. En la consola vemos aparece esto:

$ node Ej-03.js 
Escuchando en puerto: 8080
 Nombre: null
 Apellidos: null
 Nombre: Darth
 Apellidos: Vader

En la página de respuesta está el nombre de Darth Vader también:

Volvemos al formulario e introducimos el nombre de Chuck Norris:

Escuchando en puerto: 8080
 Nombre: null
 Apellidos: null
 Nombre: Darth
 Apellidos: Vader
 Nombre: null
 Apellidos: null
 Nombre: Chuck
 Apellidos: Norris

En la página de respuesta vemos esto

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. La transferencia de las Cookies se hace en las Cabeceras de los mensajes de respuesta y solicitud

Cuando un Navegador tiene Cookies de un determinado servidor, las incluye en TODAS las peticiones que haga a este servidor. De esta forma, el servidor sabe cosas sobre el cliente: quién es o si tiene productos en su carrito de la compra por ejemplo

En esta figura se resume el funcionamiento de una cookie utilizada para la autenticación del usuaruio Chuck Norris (Aunque Chuck Norris no necesita autenticarse: todos los servidores lo conocen 😂️)

A través de un formulario introduce su información para autenticarse: nombre de usuario y password. Al apretar el botón de Login se envía la información al servidor. Esto comprueba si los datos son correctos y como es el caso, crea un identificador único para Chuck Norris y se lo envía en la cabecera del mensaje de respuesta (A esto se le llama establecer una cookie)

El navegador recibe el mensaje de respuesta. Lee la cookie y la almacena. A partir de ahora, en TODAS LAS PETICIONES que realice al servidor X incluirá esta cookie. El servidor recibe miles de peticiones. La petición que llegue con esta cookie sabe que es de Chuck Norris

Sintáxis de las Cookies

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"

El servidor envía la cookie por medio de la cabecera Set-Cookie. Se usa una para cada par nombre - valor

Set-Cookie: user=Chuck
Set-Cookie: cart=producto1

El cliente envía la cookie completa (todos los pares nombre-valor) en cada mensaje de solicitud con la cabecera: Cookie

Cookie: user=Chuck; cart=producto1

Viendo las cookies en el navegador

Entre las herramientas del desarrollador disponibles en el navegador encontramos el Storage Inspector que nos permite ver todo lo que está almacenado en el Navegador. Entre otras cosas podemos ver las cookies que están actualmente almacenadas para cada dominio

Para probarlo vamos a conectarnos a nuestra página de usuario de github y a abrir el inspector de almacenamiento desde Web developer/Storage inspector

En el panel inferior izquierdo vemos todos los elementos que se almacenan en el Navegador. Pinchamos en Cookies y en el dominio https://github.com. Las dos primeras columnas se correspondens con los pares nombre - valor que están actualmente almacenados. Si seleccionamos un valor obtenemos más información en la parte de la derecha. Por ejemplo, la propiedad dotcom_user es el nombre de usuario de github. En mi caso su valor es Obijuan

Pinchando en el valor con el botón derecho nos aparece un menú contextual que nos permite añadir valores, borrarlos, etc... Esto será necesario utilizarlo para hacer pruebas de nuestra tienda, en las prácticas

Ahora nos vamos al monitor de red (Pestaña Network) y recargamos la página de github. Pinchamos en la primera solicitud y en la pestaña Headers para ver sus cabeceras. Desplazamos el panel derecho hacia abajo para ver las cabeceras del mensaje de solicitud. Ahi podemos ver cómo efectivamente en el mensaje de solicutd se han enviado todos los pares nombre-valor que tiene el navegador almacenados. Están dentro de la cabecera Cookie

Usando Cookies en Node.js

La cookie que vienen en el mensaje de solicitud la leemos mediante el método req.headers.cookie. El código que usaremos será:

//-- Leer la cookie
const cookie = req.headers.cookie;

if (cookie) {
    //-- Si hay cookie definida...
    //-- Hacer lo que toque...
} else {  //-- NO hay ninguna cookie definida
    //-- Hacer lo que toque
}

Para establecer un valor de la cookie en el mensaje de respuestas usamos el método res.setHeader('Set-Cookie', Valor), donde valor es una cadena

Ejemplo 4: Mostrando la cookie recibida

En este ejemplo se usa un "Happy Server" que muestra en la consola la cookie recibida en la petición, si la hubiese. El código es el siguiente:

//-- Imprimir la cookie recibida

const http = require('http');
const fs = require('fs');
const PUERTO = 8080;

//-- Cargar pagina web de prueba
const EJ4_HTML = fs.readFileSync('Ej-04.html','utf-8');

//-- SERVIDOR: Bucle principal de atención a clientes
const server = http.createServer((req, res) => {

  //-- Leer la Cookie recibida y mostrarla en la consola
  const cookie = req.headers.cookie;

  if (cookie) {
    console.log("Cookie: " + cookie);
  }
  else {
    console.log("Petición sin cookie");
  }

  //-- Determinar el contenido del mensaje de respuesta
  let content_type = "text/html";
  let content = EJ4_HTML;

  //-- Enviar la respuesta
  res.setHeader('Content-Type', content_type);
  res.write(content);
  res.end()

});

server.listen(PUERTO);
console.log("Escuchando en puerto: " + PUERTO);

Con Curl se prueba muy fácilmente. Lanzamos dos peticiones. La primera no tiene cookie. En la segunda se especifican dos valores dentro de la cookie. Usamos la opción -H "Cookie: valor" de curl para establecer la cookie

Peticiones:

curl localhost:8080
curl -H "Cookie: user=obijuan; carrito=FPGA" localhost:8080

En la consola de node veremos lo siguiente:

$ node Ej-04.js 
Escuchando en puerto: 8080
Petición sin cookie
Cookie: user=obijuan; carrito=FPGA

También lo podemos probar con el navegador. Lanzamos la primera petición: http://localhost:8080/ y abrimos el visualizador de cookies. Como es la primera vez, no tenemos ninguna definida para este dominio:

Pinchando en la tecla + de la derecha y a continuación en el símbolo de recarga que está a su derecha añadimos una cookie aleatoria, que podemos editar haciendo doble click en su nombre si queremos

Si ahora recargamos la página, la cookie se incluye en la petición, y la veremos en la consola:

En cualquier petición que hagamos se incluye la cookie. Si la borramos comprobaremos que no aparece en el mensaje recibido por el servidor

Ejemplo 5: Página de saludo

En este ejemplo se muestra una página de prueba de una tienda. Si en la solicitud NO hay una cookie con el valor user definido se muestra esta página:

Si la solicitud tiene una cookie en la que se encuentra el identificador user asignado al nombre del usuario (user=nombre) entonces se muestra el nombre del usuario: el servidor ha recocido al usuario

Se pueden hacer pruebas fácilmente desde el Storage Inpector, asignando nuevos identificadores en la cookie, o eliminándonos:

El código es el siguiente, y su funcionamiento se explica a continuación:

//-- Página dinámica que detecta si la petición ha
//-- venido de un usuario
//-- Para ello se detecta si en la cookie hay un par
//-- nombre-valor de la forma "user=nombre";

const http = require('http');
const fs = require('fs');
const PUERTO = 8080;

//-- Cargar pagina web de prueba
const EJ5_HTML = fs.readFileSync('Ej-05.html','utf-8');

//-- SERVIDOR: Bucle principal de atención a clientes
const server = http.createServer((req, res) => {

  //-- Determinar el contenido del mensaje de respuesta
  let content_type = "text/html";
  let content = EJ5_HTML.replace("HTML_EXTRA","");

  //-- Leer la Cookie recibida y mostrarla en la consola
  const cookie = req.headers.cookie;

  //-- Hay cookie
  if (cookie) {
    
    //-- Obtener un array con todos los pares nombre-valor
    let pares = cookie.split(";");
    
    //-- Variable para guardar el usuario
    let user;

    //-- Recorrer todos los pares nombre-valor
    pares.forEach((element, index) => {

      //-- Obtener los nombres y valores por separado
      let [nombre, valor] = element.split('=');

      //-- Leer el usuario
      //-- Solo si el nombre es 'user'
      if (nombre.trim() === 'user') {
        user = valor;
      }
    });

    //--- Si la variable user está asignada
    if (user) {

      //-- Añadir a la página el nombre del usuario
      console.log("user: " + user);
      content = EJ5_HTML.replace("HTML_EXTRA", "<h2>Usuario: " + user + "</h2>");
    }

  }

  //-- Enviar la respuesta
  res.setHeader('Content-Type', content_type);
  res.write(content);
  res.end()

});

server.listen(PUERTO);
console.log("Escuchando en puerto: " + PUERTO);

La plantilla de la página está en el fichero Ej-05.html. Es un HTML en el que se ha definido el parámetro HTML_EXTRA para incluir información adicional, utilizando el método replace

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ejemplo 5</title>
</head>
<body>
    <h2>Bienvenido a mi tienda</h2>
    <p>Página para pruebas.....</p>
    <p></p>
    HTML_EXTRA
</body>
</html>

Esta plantilla se carga inicialmente (de forma síncrona) en la variable EJ5_HTML. Al llegar una solicitud pueden pasar dos cosas

  • Que NO tenga cookie. En ese caso no se añade nada adicional a la página, por lo que el identificador HTML_EXTRA se sustituye por la cadena vacía y lo que se muestra es la página normal

  • Que tenga cookie. Hay que obtener todos los pares nombre-valor. La separación de estos pares se realiza de forma muy sencilla utilizando el método spli(";"). Devuelve un Array con todos los fragmentos de cadena que están separados por el carácter ;. Ahora hay que recorrer estos fragmentos obteniendo los nombres y los valores, que se almacenan en las variables nombre y valor. Dentro de cada par, la separación se realiza utilizando el método split('='). Si resulta que se la variable nombre contiene la palabra 'user', entonces se asignal el nombre del usuario a la variable user

Por tanto, sólo en el caso en que se encuentre la cadena user=nombre en la cookie se identifica al usuario que ha accedido. Ya sólo falta sustituri HTML_EXTRA por el código html para mostrar el usuario en la web

Ejemplo 6: Login simple

En este ejemplo se muestra un sistema de login muy básico. Partimos del estado inicial: no tenemos cookie en el navegador, y accedermos a la página principal. Nos aparece lo siguiente:

Como NO tenemos la cookie, no nos reconoce como usuario. En la página principal tenemos la opción de Conectarnos. Pinchamos en Login. Aquí nos debería sacar un formulario para realizar la autenticación (usuario y login), pero como es un ejemplo básico para entender cómo funciona, directamente accedemos al recurso /login donde suponemos que la autenticación ha sido correcta, y que nuestro usuario es chuck

El servidor asigna la cookie user=chuck y la devuelve junto con la página que indica que el login se ha realizado correctamente:

Ahora pinchamos en el enlace de la página principal. Al volver a acceder a ella el navegador envía la cookie y el servidor nos reconoce como el usuario Chuck y nos lo indica en la página

El código completo es este:

//-- Ejemplo de login básico
//-- La página principal detecta al usuario
//-- Se puede acceder como usuario Chuck desde
//-- el recurso /login

const http = require('http');
const fs = require('fs');
const PUERTO = 8080;

//-- Cargar pagina web de prueba
const EJ6_HTML = fs.readFileSync('Ej-06.html','utf-8');
const LOGIN = fs.readFileSync('Ej-06-login.html', 'utf-8');

//-- Analizar la cookie y devolver el nombre del
//-- usuario si existe, o null en caso contrario
function get_user(req) {

  //-- Leer la Cookie recibida
  const cookie = req.headers.cookie;

  //-- Hay cookie
  if (cookie) {
    
    //-- Obtener un array con todos los pares nombre-valor
    let pares = cookie.split(";");
    
    //-- Variable para guardar el usuario
    let user;

    //-- Recorrer todos los pares nombre-valor
    pares.forEach((element, index) => {

      //-- Obtener los nombres y valores por separado
      let [nombre, valor] = element.split('=');

      //-- Leer el usuario
      //-- Solo si el nombre es 'user'
      if (nombre.trim() === 'user') {
        user = valor;
      }
    });

    //-- Si la variable user no está asignada
    //-- se devuelve null
    return user || null;
  }
}

//-- SERVIDOR: Bucle principal de atención a clientes
const server = http.createServer((req, res) => {

  //-- Construir el objeto url con la url de la solicitud
  const myURL = new URL(req.url, 'http://' + req.headers['host']);  

  //-- Determinar el contenido del mensaje de respuesta
  let content_type = "text/html";
  let content = EJ6_HTML.replace("HTML_EXTRA","");

  //-- Obtener le usuario que ha accedido
  //-- null si no se ha reconocido
  let user = get_user(req);

  console.log("User: " + user);

  //-- Acceso al recurso raiz
  if (myURL.pathname == '/') {

    //--- Si la variable user está asignada
    if (user) {

        //-- Añadir a la página el nombre del usuario
        console.log("user: " + user);
        content = EJ6_HTML.replace("HTML_EXTRA", "<h2>Usuario: " + user + "</h2>");
    } else {
        //-- Mostrar el enlace a la página de login
        content = EJ6_HTML.replace("HTML_EXTRA", `
        <a href="login">[Login]</a>
        `);
    }

    //-- Acceso a otro recurso: Se hace login
  } else if (myURL.pathname == '/login') {

    //-- Asignar la cookie de usuario Chuck
    res.setHeader('Set-Cookie', "user=Chuck");

    //-- Asignar la página web de login ok
    content = LOGIN;
  } else {
      content = "ERROR!!!";
  }
     
  //-- Enviar la respuesta
  res.setHeader('Content-Type', content_type);
  res.write(content);
  res.end();

});

server.listen(PUERTO);
console.log("Escuchando en puerto: " + PUERTO);

Se ha creado la función get_user() para obtener el usuario a partir de la cookie. Al recibir una solicitud se analiza el recurso al que acceder. Si es la página principal, se añade al final uno HTML u otro dependiendo de si se ha detectado al usuario o no. Si el recurso es /login se establece el nombre del usuario en la cookie user=Chucky se devuelve la página de login correcto

En esta animación se muestra el funcionamiento. Se ha dejado abierto el Store inspector para ver el estado de las cookies

Carrito de la compra

Una forma de implementar un carrito de la compra es utilizar las cookies para almacenar ahí los productos que se han añadido al carrito. Cada vez que el usuario le pida al servidor que quiere añadir un producto al carrito, el servidor lo añade en una cookie

Es el programador el que tiene que definir cómo organizar los productos en la cookie. Una posibilidad es definir el identificador carrito y meter en su cadena los diferentes productos separados por ejemplo por el carácter :

carrito=producto1:producto2;

Una vez que la compra se ha realizado, el carrito ya se puede vaciar, asignando por ejemplo la cadena nula: carrito=

Autor

Créditos

Licencia

Enlaces

TEORIA

Soluciones

LABORATORIO

Prácticas y sesiones de laboratorio

Práctica 0: Herramientas

Práctica 1: Node.js: Tienda Básica

Práctica 2: Interacción cliente-servidor. Tienda mejorada

Práctica 3: Websockets: Chat

Practica 4: Electron: Home Chat

  • L11: Home chat (26-Abril-2022)
  • L12: Laboratorio puro. NO hay contenido nuevo (9-Mayo-2022)
  • L13: Laboratorio/Tutorias. No hay contenido nuevo (10-Mayo-2022)

EXAMENES

Curso 2020-2021

Clone this wiki locally