Casi todo lo que hace Express, desde leer JSON hasta servir archivos o comprobar un login, está construido con middleware. Entender cómo funciona es entender Express. En el libro Node.js desde cero el middleware tiene un capítulo propio porque es la base de la autenticación, la validación y el manejo de errores que vienen después.
Qué es un middleware
Un middleware es una función con tres parámetros: (req, res, next). Express las encadena,
y cada petición las atraviesa en orden. Cada una puede:
- Leer o modificar la petición o la respuesta (por ejemplo, añadir
req.usuario). - Terminar la petición enviando una respuesta.
- Pasar el control al siguiente middleware llamando a
next().
petición ─▶ express.json() ─▶ logger ─▶ autenticar ─▶ ruta ─▶ respuesta
│
└─▶ 401 si no hay token (la cadena se corta aquí)
next(), la petición queda colgada hasta que el
cliente se canse de esperar.
El orden importa
Los middlewares se ejecutan en el orden en que se registran con app.use():
import express from 'express';
const app = express();
app.use(express.json()); // 1. primero: deja req.body listo
app.use(express.static('public')); // 2. archivos estáticos: si existe, responde y termina
app.use(logger); // 3. registra cada petición que llega hasta aquí
app.use('/api/admin', soloAdmin); // 4. solo para las rutas que empiezan por /api/admin
app.get('/api/posts', listarPosts); // 5. las rutas
app.use((req, res) => { // 6. si nada respondió: 404
res.status(404).json({ error: 'Ruta no encontrada' });
});
Un error clásico es registrar express.json() después de las rutas: cuando la ruta
se ejecuta, req.body todavía no existe.
Escribir tus propios middlewares
Un logger con tiempo de respuesta
export function logger(req, res, next) {
const inicio = performance.now();
// 'finish' se emite cuando la respuesta terminó de enviarse
res.on('finish', () => {
const ms = (performance.now() - inicio).toFixed(1);
console.log(`${req.method} ${req.originalUrl} → ${res.statusCode} (${ms} ms)`);
});
next();
}
Un id único por petición
import { randomUUID } from 'node:crypto';
export function requestId(req, res, next) {
req.id = randomUUID();
res.set('X-Request-Id', req.id); // útil para cruzar errores del cliente con los logs
next();
}
Un middleware configurable
Si necesitás parámetros, escribí una función que devuelva el middleware:
export function requiereRol(...roles) {
return (req, res, next) => {
if (!req.usuario) {
return res.status(401).json({ error: 'No autenticado' });
}
if (!roles.includes(req.usuario.rol)) {
return res.status(403).json({ error: 'No tenés permiso para esta acción' });
}
next();
};
}
// Uso: app.delete('/api/posts/:id', autenticar, requiereRol('admin', 'editor'), borrarPost);
El middleware autenticar, que verifica el token y rellena req.usuario, lo
construimos en autenticación con JWT.
Middleware por ruta
Además de app.use() para todas las rutas, podés aplicar middlewares solo a una ruta o a un
router, pasándolos antes del manejador final:
// Solo esta ruta exige estar autenticado y ser admin
app.get('/api/usuarios', autenticar, requiereRol('admin'), listarUsuarios);
// Todas las rutas de este router exigen autenticación
const privado = Router();
privado.use(autenticar);
privado.get('/perfil', verPerfil);
app.use('/api/me', privado);
Middlewares de terceros imprescindibles
| Paquete | Qué hace |
|---|---|
helmet | Añade cabeceras HTTP de seguridad (CSP, HSTS, etc.) |
cors | Controla qué dominios pueden llamar a tu API desde el navegador |
express-rate-limit | Limita el número de peticiones por IP: frena fuerza bruta y abusos |
compression | Comprime las respuestas (si no lo hace ya tu proxy inverso) |
import cors from 'cors';
import helmet from 'helmet';
import { rateLimit } from 'express-rate-limit';
app.use(helmet());
app.use(cors({ origin: ['https://mi-frontend.com'] })); // nunca '*' si usás credenciales
app.use('/api/auth', rateLimit({ windowMs: 15 * 60 * 1000, limit: 20 })); // 20 intentos / 15 min
Hay un tipo especial de middleware, con cuatro parámetros
(err, req, res, next), que solo se ejecuta cuando hay un error. Lo vemos en
validación y manejo de errores.
La pieza central de Express
El libro Node.js desde cero dedica un capítulo al middleware y su aplicación, la base de la autenticación, la validación y el manejo de errores.
Comprar en Amazon