Un middleware en Express es una función con la firma (req, res, next) que se ejecuta entre el momento en que llega una petición y el momento en que se envía la respuesta. Cada middleware puede leer o cambiar req y res, terminar la petición enviando una respuesta, o llamar a next() para pasar la petición a la siguiente función de la cadena. app.use(fn) añade un middleware para todas las peticiones, y Express lo ejecuta todo en el orden en que lo registraste.
La Console registra los tres pasos en orden en cada petición, y la ruta lee req.startedAt, una propiedad que añadió el logger. Envía GET /missing: los dos middleware siguen registrando, porque app.use() coincide con todas las rutas, y luego Express responde 404 porque ninguna ruta coincidió.
Olvidar next()
Un middleware que ni envía una respuesta ni llama a next() deja la petición colgada. El cliente espera hasta que se agota el tiempo y no aparece nada en los logs, lo que lo convierte en un bug de middleware común. Borra next(); de logger arriba y vuelve a enviar GET /: la petición nunca recibe respuesta.
La regla es simple: cada camino dentro de un middleware termina exactamente en una de estas:
next()para continuar,next(err)para saltar al error handler (consulta manejo de errores en Express),- una respuesta como
res.json()ores.status(401).send().
Llamar a next() después de enviar una respuesta también es un bug. El siguiente handler intenta enviar una segunda respuesta y Express lanza ERR_HTTP_HEADERS_SENT. Escribe return res.status(401).json(...) para que la función se detenga ahí.
Una comprobación de auth que detiene la petición
Un middleware que rechaza una petición envía la respuesta él mismo y nunca llama a next(). Pásalo como argumento extra a una ruta para proteger solo esa ruta:
La primera petición recibe 401 con {"error":"Missing or wrong API key"}. Añade el header x-api-key: secret123 en la barra de petición y vuelve a enviarla: ahora la respuesta es {"users":42,"caller":"reporting-app"}. /public nunca ejecuta la comprobación.
Dónde se ejecuta el middleware
| Escribes | Se ejecuta para |
|---|---|
app.use(fn) | Todas las peticiones, cualquier método |
app.use('/api', fn) | Rutas que empiezan por /api |
app.get('/admin', fn, handler) | Solo GET /admin, antes de handler |
router.use(fn) | Todas las rutas de ese router |
El orden forma parte del significado. Un logger registrado después de las rutas nunca registra las peticiones que esas rutas respondieron, porque una ruta que envía una respuesta no llama a next(). Registra primero el middleware de toda la app, como el logging, el parseo del body y CORS, luego las rutas, y después los handlers de 404 y de errores.
Middleware integrado
Express incluye algunas funciones de middleware que añades con app.use(). Los parsers del body rellenan req.body; sin ellos es undefined.
| Middleware | Qué hace |
|---|---|
express.json() | Parsea bodies JSON (Content-Type: application/json) |
express.urlencoded() | Parsea envíos de formularios HTML (name=Ada&age=36) |
express.text() | Pone un body de texto plano en req.body como string |
express.static('public') | Sirve archivos desde una carpeta |
Envía POST /echo con el body {"name": "Ada"} y la respuesta incluye "body":{"name":"Ada"}. Quita la línea de express.json(), vuelve a enviarla y body desaparece de la respuesta: req.body es undefined, y JSON.stringify omite los valores undefined. Paquetes como cors, helmet y morgan también son middleware: los instalas con npm install y se los pasas a app.use() igual. La página de express.static cubre cómo servir archivos.
Errores comunes
Llamar al middleware en lugar de pasarlo. app.use(logger()) ejecuta logger una vez al arrancar y registra lo que devuelve. Escribe app.use(logger). (express.json() lleva paréntesis porque devuelve una función de middleware.)
Añadir el parser del body después de las rutas. Las rutas se ejecutan primero y ven req.body como undefined.
Esperar que app.use('/admin', fn) coincida con una sola ruta. También se ejecuta para /admin/users y para cualquier otra ruta bajo /admin, con cualquier método. Para proteger una sola ruta, pasa el middleware a app.get('/admin', fn, handler).
Preguntas frecuentes
¿Qué diferencia hay entre un middleware y un route handler?
Técnicamente ninguna: los dos son funciones de (req, res, next). Por convención, un route handler termina la petición con una respuesta, mientras que un middleware suele hacer un trabajo común y llama a next().
¿Un middleware puede ser async?
Sí. En Express 5, un middleware async que lanza un error o devuelve una promesa rechazada envía el error a tu error handler automáticamente. Haz await de lo que necesites y luego llama a next().
¿Qué hace next('route')?
Se salta los handlers que quedan de la ruta actual y pasa a la siguiente ruta que coincida. Solo funciona en handlers añadidos con app.get(), app.post() y las demás funciones de método, no en app.use().
¿Cómo me salto un middleware en una ruta concreta?
Registra esa ruta antes del middleware, para que responda primero, o comprueba la ruta dentro del middleware (if (req.path === '/health') return next();). Aplicar el middleware por router o por ruta en lugar de a toda la app suele quitar esa necesidad.