Menu

Middleware en Express: cómo funciona next(), con ejemplos

Un middleware de Express es una función (req, res, next) que se ejecuta antes de tu route handler. Puede leer o cambiar la petición, terminarla con una respuesta o llamar a next() para pasarla al siguiente.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

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() o res.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

EscribesSe 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.

MiddlewareQué 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.

Ilustración de los lenguajes de programación de Coddy

Aprende a programar con Coddy

Comenzar