Hoy · Hoja de ruta
- 1. Aprende: Cuándo conviene generar el HTML en el servidor y cómo se hace sin abrir un agujero.
- 2. Haz: Sirve una página de catálogo generada en el servidor.
- 3. Comprueba: Un producto con etiquetas en el nombre no rompe ni ejecuta nada.
Antes de empezar · 5 minutos, sin apuntes
- En la UD4 el catálogo se pintaba en el navegador. ¿Qué ve alguien con JavaScript desactivado?
- ¿Y un buscador que indexa tu web?
- ¿Qué pasaría si el nombre de un producto contuviera una etiqueta?
Las dos formas de pintar
| Dónde se genera | Ventajas | Inconvenientes |
|---|---|---|
| En el servidor | Llega listo, funciona sin JavaScript, se indexa | Cada cambio recarga la página |
| En el cliente | Interacción inmediata, menos trabajo del servidor | Depende de que el código se ejecute |
No hay que elegir una para siempre: lo habitual es que la primera carga llegue hecha del servidor y la interacción se resuelva en el cliente. Es exactamente lo que vas a montar: la página de catálogo llega renderizada, y los filtros siguen funcionando en el navegador como en la UD4.
Generar HTML con plantillas del lenguaje
export function paginaCatalogo(productos) {
return `<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>${escapar("Catálogo")}</title>
<link rel="stylesheet" href="/css/styles.css">
<script type="module" src="/js/main.js"></script>
</head>
<body>
<main>
<h1>Catálogo</h1>
<ul class="catalogo" data-js="catalogo">
${productos.map(tarjeta).join("")}
</ul>
</main>
</body>
</html>`;
}
function tarjeta(producto) {
return `<li class="producto" data-id="${producto.id}">
<h3>${escapar(producto.nombre)}</h3>
<p class="precio">${escapar(formatearPrecio(producto.precio))}</p>
</li>`;
}
No hace falta instalar un motor de plantillas: las plantillas del lenguaje, las de la UD3, sirven perfectamente para esto. Un motor aporta herencia de plantillas y sintaxis propia; a cambio, una dependencia más y un lenguaje más que aprender.
Escapar no es opcional
const ESCAPES = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" };
export function escapar(valor) {
return String(valor).replace(/[&<>"']/g, (caracter) => ESCAPES[caracter]);
}
Todo dato que entra en el HTML se escapa
Si un producto se llama Teclado <script>…</script> y se inserta sin escapar, ese código se ejecuta en el navegador de quien visite tu página, con sus permisos y sus datos de sesión. Esa vulnerabilidad se denomina cross-site scripting y es la vulnerabilidad más extendida de la web.
Es el mismo problema del innerHTML de la UD4, ahora del lado del servidor y peor: allí afectaba a quien lo escribía, aquí a todo el que visite la página.
Y ojo con el sitio donde insertas: escapar sirve para el contenido y para los atributos entrecomillados. Meter datos de fuera dentro de un bloque de código de la página o en una URL requiere reglas distintas; lo sensato es no hacerlo.
Tarea 10 · La página del servidor
- Escribe
src/vistas/catalogo.jsque genere la página completa. - Escribe y usa la función de escapado en todos los datos.
- Sirve la página en
GET /desde su router. - Comprueba con «ver código fuente» que el HTML llega hecho.
- Añade un producto con etiquetas en el nombre y comprueba que se ve como texto.
- Valida el HTML generado en el W3C.
Checkpoint · fin de la sesión 10
- Generas HTML en el servidor con plantillas del lenguaje.
- Escapas todo dato antes de insertarlo.
- El HTML generado es válido y semántico.
- Explicas qué es el cross-site scripting.
Ver respuestas
1 · Que llega hecha y funciona sin JavaScript, y que los buscadores la leen.
2 · Sustituir los caracteres con significado en HTML por sus entidades.
3 · Que se ejecute código ajeno en el navegador de cualquier visitante.