Cómo Funciona el Middleware en Node.js
Has visto app.use() disperso por todas partes en bases de código de Express. Sabes que el middleware se sitúa entre las solicitudes y las respuestas. Pero cuando algo se rompe en esa cadena—una solicitud se cuelga, un error desaparece, o los manejadores se ejecutan en el orden incorrecto—el modelo mental se desmorona.
Este artículo explica cómo funciona realmente el middleware de Node.js: qué es, cómo fluye el control a través de la cadena, y qué cambió en Express 5.
Puntos Clave
- El middleware es un patrón de framework, no una característica de Node.js—Express lo implementa sobre el módulo
httpdel núcleo - El orden de ejecución importa: el middleware se ejecuta en orden de registro, y los manejadores de errores deben ir al final
- La función
next()controla el flujo; omitirla sin enviar una respuesta causa que las solicitudes se cuelguen - Express 5 captura nativamente las promesas rechazadas de middleware asíncrono y manejadores de rutas, eliminando la necesidad de wrappers manuales
El Middleware Es un Patrón de Framework, No una Característica de Node.js
Node.js en sí mismo no tiene concepto de middleware. El módulo http del núcleo te proporciona un objeto de solicitud y respuesta—nada más. El middleware es un patrón que frameworks como Express implementan sobre Node.js.
El middleware de Express sigue una estructura específica: funciones que reciben req, res, y next. El framework mantiene una pila de estas funciones y las llama secuencialmente para cada solicitud entrante. Este ciclo de vida de solicitud en frameworks de Node.js es lo que le da su poder al middleware.
Otros frameworks implementan patrones similares de manera diferente. Koa usa un “modelo de cebolla” donde el middleware envuelve manejadores subsecuentes. Fastify usa hooks en puntos específicos del ciclo de vida. El concepto se transfiere, pero la semántica no.
El Ciclo de Vida Solicitud-Respuesta
Cuando una solicitud llega a una aplicación Express, entra en un pipeline:
- Express compara la solicitud contra el middleware y rutas registradas
- Cada función middleware se ejecuta en orden de registro
- El control pasa hacia adelante mediante
next()o se detiene cuando se envía una respuesta - El middleware de manejo de errores captura errores pasados a
next(err)y errores lanzados o rechazados dentro del middleware y manejadores de rutas gestionados por Express
La función next() es el mecanismo que mueve el control a través de la cadena. Llámala, y Express invoca el siguiente middleware coincidente. Omítela sin enviar una respuesta, y la solicitud se cuelga indefinidamente.
El Orden del Middleware Importa
El middleware de Express se ejecuta en el orden en que lo registras. Esto no es solo un detalle—es la base de los patrones de middleware en Node.js.
app.use(parseBody)
app.use(authenticate)
app.use(authorize)
app.get('/data', handler)
Aquí, parseBody se ejecuta primero, haciendo que los datos de la solicitud estén disponibles para authenticate. Intercambia su orden, y la autenticación falla porque el cuerpo aún no ha sido parseado.
Este orden también afecta el manejo de errores. El middleware de manejo de errores debe venir después de las rutas que protege.
Cortocircuito de la Respuesta
El middleware puede finalizar el ciclo solicitud-respuesta tempranamente enviando una respuesta sin llamar a next(). Así es como el middleware de autenticación rechaza solicitudes no autorizadas:
function requireAuth(req, res, next) {
if (!req.user) {
return res.status(401).json({ error: 'Unauthorized' })
}
next()
}
Una vez que res.send(), res.json(), o métodos similares se ejecutan, el middleware subsecuente no se ejecutará para esa solicitud. Este cortocircuito es intencional y útil.
Discover how at OpenReplay.com.
Middleware a Nivel de Aplicación, Router y Ruta
El middleware de Express se adjunta en diferentes ámbitos:
Middleware a nivel de aplicación se ejecuta para cada solicitud a la aplicación. Usa app.use() para preocupaciones transversales como logging o parseo del cuerpo.
Middleware a nivel de router se ejecuta para solicitudes que coinciden con un router específico. Esto delimita el middleware a grupos de rutas sin afectar toda la aplicación.
Middleware a nivel de ruta se ejecuta solo para rutas específicas. Pasa funciones middleware directamente a definiciones de rutas para comportamiento dirigido como validación.
La distinción es sobre el ámbito, no la capacidad. Los tres usan la misma firma de función.
Manejo de Errores y Middleware en Express 5
Express identifica el middleware de manejo de errores por su firma de cuatro parámetros: (err, req, res, next). Cuando cualquier middleware llama a next(err) o lanza un error, Express omite el middleware regular y salta a los manejadores de errores.
Express 5 cambia cómo funcionan los errores asíncronos. En Express 4, las promesas rechazadas y excepciones asíncronas requerían manejo manual o wrappers de terceros. Express 5 captura nativamente las promesas rechazadas de funciones asíncronas y las enruta a manejadores de errores automáticamente.
// Express 5: no se necesita wrapper
app.get('/data', async (req, res) => {
const data = await fetchData() // el rechazo activa el middleware de error
res.json(data)
})
app.use((err, req, res, next) => {
res.status(500).json({ error: err.message })
})
El middleware de manejo de errores todavía necesita registrarse al final, después de las rutas y otro middleware.
Conclusión
El middleware es un patrón a nivel de framework para procesar solicitudes a través de una cadena de funciones. Comprender el orden de ejecución, el rol de next(), y dónde colocar los manejadores de errores elimina la mayoría de los dolores de cabeza al depurar middleware.
El manejo nativo de errores asíncronos de Express 5 elimina un punto de dolor común, pero los fundamentos permanecen: registra el middleware en el orden correcto, llama a next() o envía una respuesta, y coloca los manejadores de errores al final.
Preguntas Frecuentes
Si olvidas llamar a next() y no envías una respuesta, la solicitud se colgará indefinidamente. Express espera que se llame a next() para continuar la cadena, o que se envíe una respuesta al cliente. Siempre asegúrate de que tu middleware llame a next() para pasar el control hacia adelante o envíe una respuesta para finalizar el ciclo.
Sí, pero debes manejar los errores manualmente. Express 4 no captura promesas rechazadas automáticamente, por lo que los rechazos no manejados no activarán tu middleware de manejo de errores. Envuelve el código asíncrono en bloques try-catch o usa una función wrapper que reenvíe errores a next(). Express 5 elimina este requisito capturando rechazos nativamente.
El middleware de manejo de errores requiere exactamente cuatro parámetros: err, req, res, y next. Si omites cualquier parámetro, Express lo trata como middleware regular y lo omite durante el manejo de errores. También verifica que tu manejador de errores esté registrado después de todas las rutas y otro middleware en tu aplicación.
Ambos registran middleware con la misma firma de función, pero difieren en ámbito. app.use() adjunta middleware a nivel de aplicación, ejecutándose para todas las solicitudes. router.use() adjunta middleware a una instancia específica de router, ejecutándose solo para solicitudes que coincidan con la ruta montada de ese router.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.