El método
- ¿Qué datos hay, y dónde viven?
- ¿Qué reglas tienen, sin pensar todavía en HTTP?
- ¿Qué se puede pedir desde fuera, con qué método y qué ruta?
- ¿Qué responde cada caso, incluidos los que fallan?
- ¿Qué queda registrado, y qué no debe salir nunca?
La idea más importante
Escríbelo a mano una vez. Después usa el framework sabiendo qué te está resolviendo.
Vale para Express hoy y para Spring Boot el año que viene. Un framework es un conjunto de respuestas a problemas concretos; si no conoces los problemas, sus respuestas son magia, y la magia no se puede depurar.
Su elemento complementario, el que gobierna todo lo que viene, es este:
El servidor no se fía de nadie
Todo lo que llega de fuera —el cuerpo de una petición, un parámetro, una ruta de fichero— es sospechoso hasta que se valida. La validación del cliente es comodidad; la del servidor es la única que nadie puede saltarse.
No memorices Node
- ¿Esto lo resuelve Node de fábrica, o necesito de verdad una dependencia?
- ¿Este valor cambia entre máquinas? Entonces va al entorno.
- ¿Esta operación bloquea el proceso?
- ¿Qué pasa si el fichero no existe, o no tengo permisos?
- ¿De quién es el fallo: 4xx o 5xx?
- ¿Estoy devolviendo información interna en el mensaje de error?
- ¿Quién valida esto, y qué pasa si el cliente miente?
- ¿En qué orden se declaran mis middlewares?
- ¿Esta ruta puede salirse de la carpeta que le corresponde?
Al terminar deberías poder responder
- ¿Qué es Node.js y qué desaparece respecto al navegador?
- ¿Qué hay en
process.argvy por qué se descartan dos posiciones? - ¿Por qué la configuración va en variables de entorno?
- ¿Qué significa un código de salida distinto de cero?
- ¿Qué diferencia hay entre ESM y CommonJS?
- ¿Qué declara
package.jsony para qué sirven sus scripts? - ¿Qué acepta
^1.2.3? - ¿Para qué sirve
package-lock.jsony por qué se sube? - ¿Por qué no se sube
node_modules? - ¿Qué te preguntas antes de instalar una dependencia?
- ¿Por qué usamos la API de ficheros con promesas y no la síncrona?
- ¿Qué significa
ENOENTy cómo se trata? - ¿Por qué se componen las rutas con
path.join? - ¿Por qué se escribe en un temporal y se renombra?
- ¿Qué dos límites tiene un fichero JSON como almacén?
- ¿Qué diferencia hay entre un error esperable y uno inesperado?
- ¿Qué hace un servidor HTTP, paso a paso, con cada petición?
- ¿Qué tres cosas se escriben en una respuesta?
- ¿Por qué el cuerpo de la petición se lee por trozos?
- ¿Qué significan 200, 201, 400, 404, 405 y 500?
- ¿Qué dice la familia del código sobre de quién es el problema?
- ¿Qué es el path traversal y cómo se evita?
- ¿Por qué hay que enviar el tipo de contenido correcto?
- ¿Qué seis problemas del servidor a mano resuelve Express?
- ¿Qué hace
express.json()y dónde se declara? - ¿Qué es un middleware y qué pasa si no llama a
next? - ¿Cómo se distingue un manejador de errores de un middleware normal?
- ¿Por qué el cliente nunca debe ver una traza?
- ¿Cómo averiguas si un fallo es del cliente o del servidor?
- ¿Por qué desaparece el problema de CORS al servir todo desde el mismo origen?
El vocabulario de la unidad
| Concepto | Significa |
|---|---|
| Node.js | Un entorno para ejecutar JavaScript fuera del navegador |
| Proceso | El programa en ejecución, con sus argumentos y su entorno |
| Variable de entorno | Configuración que vive fuera del código |
| Código de salida | El número con el que termina un programa: 0 es éxito |
| ESM / CommonJS | Los dos sistemas de módulos: el estándar y el heredado |
package.json |
La ficha del proyecto: scripts y dependencias |
| Versionado semántico | Mayor, menor y parche, y qué compatibilidad implica cada uno |
| Fichero de bloqueo | El registro de las versiones exactas instaladas |
| Operación síncrona | La que bloquea el proceso hasta terminar |
ENOENT |
Código de error: no existe el fichero o la carpeta |
| Escritura atómica | Escribir en un temporal y renombrar, para no dejar datos a medias |
| Puerto | El número por el que un servidor escucha |
| Petición / respuesta | Lo que envía el cliente / lo que devuelve el servidor |
| Código de estado | El número que resume qué ha pasado con la petición |
| Estático | Archivo servido sin transformación desde el disco |
| Tipo de contenido | La cabecera que dice qué es lo que se envía |
| Path traversal | Salirse de la carpeta permitida con tramos de ruta |
| Framework | Un conjunto de soluciones a problemas repetidos |
| Middleware | Un paso de la cadena por la que pasa cada petición |
| Manejador de errores | El middleware de cuatro parámetros que decide qué se responde |
| Traza | El detalle técnico de un error: para el registro, no para el cliente |
La siguiente unidad
Ya tienes un servidor que sirve tu web y responde a algunas rutas. Lo que todavía no tienes es una API diseñada.
- Rutas sueltas
- Recursos y contrato
- Capas y persistencia
- Cliente y servidor, de punta a punta
En la UD6 tus rutas dejarán de ser una colección de casos y pasarán a ser el diseño de un recurso: el CRUD completo, la separación en capas, un contrato de errores estable, la web servida y consumiendo su propia API, y la configuración y las comprobaciones que hacen falta para poder publicarlo. Cierra el módulo, y deja el camino hecho para el módulo de servidor.
Ya deberías ser capaz de
- Explicar qué es Node.js y en qué se diferencia el entorno del navegador del de un servidor.
- Ejecutar programas desde la terminal y leer argumentos y variables de entorno.
- Organizar un proyecto con package.json, scripts y dependencias declaradas.
- Instalar dependencias entendiendo el versionado semántico y el fichero de bloqueo.
- Leer y escribir ficheros con la API de promesas, componiendo rutas de forma portable.
- Usar un fichero JSON como almacén sin corromperlo.
- Levantar un servidor HTTP con el módulo nativo y responder con el código de estado correcto.
- Servir ficheros estáticos resolviendo su tipo de contenido y protegiendo las rutas.
- Explicar qué problemas resuelve Express y reescribir el servidor nativo con él.
- Escribir middleware propio, registrar las peticiones y centralizar el tratamiento de errores.