Editar en GitHub

Uso de middleware

Express es un framework web de enrutamiento y middleware que tiene una funcionalidad mínima por sí mismo: Una aplicación Express es esencialmente una serie de llamadas a funciones de middleware.

Las funciones de middleware son funciones que tienen acceso al objeto de solicitud (req), al objeto de respuesta (res), y a la siguiente función de middleware en el ciclo solicitud-respuesta de la aplicación. La siguiente función de middleware se denomina comúnmente con una variable llamada next.

Las funciones de middleware pueden realizar las siguientes tareas:

  • Ejecutar cualquier código.
  • Hacer cambios en los objetos de solicitud y respuesta.
  • Finalizar el ciclo solicitud-respuesta.
  • Llamar a la siguiente función de middleware en la pila.

Si la función de middleware actual no finaliza el ciclo solicitud-respuesta, debe llamar a next() para pasar el control a la siguiente función de middleware. De lo contrario, la solicitud quedará colgada.

Una aplicación Express puede usar los siguientes tipos de middleware:

Puedes cargar middleware a nivel de aplicación y a nivel de router con una ruta de montaje opcional. También puedes cargar una serie de funciones de middleware juntas, lo que crea una sub-pila del sistema de middleware en un punto de montaje.

Middleware a nivel de aplicación

Vincula el middleware a nivel de aplicación a una instancia del objeto app usando las funciones app.use() y app.METHOD(), donde METHOD es el método HTTP de la solicitud que la función de middleware maneja (como GET, PUT, o POST) en minúsculas.

Este ejemplo muestra una función de middleware sin ruta de montaje. La función se ejecuta cada vez que la aplicación recibe una solicitud.

index.cjs
const express = require('express');
const app = express();
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});

Este ejemplo muestra una función de middleware montada en la ruta /user/:id. La función se ejecuta para cualquier tipo de solicitud HTTP en la ruta /user/:id.

app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method);
next();
});

Este ejemplo muestra una ruta y su función manejadora (sistema de middleware). La función maneja solicitudes GET a la ruta /user/:id.

app.get('/user/:id', (req, res, next) => {
res.send('USER');
});

Aquí hay un ejemplo de carga de una serie de funciones de middleware en un punto de montaje, con una ruta de montaje. Ilustra una sub-pila de middleware que imprime información de la solicitud para cualquier tipo de solicitud HTTP a la ruta /user/:id.

app.use(
'/user/:id',
(req, res, next) => {
console.log('Request URL:', req.originalUrl);
next();
},
(req, res, next) => {
console.log('Request Type:', req.method);
next();
}
);

Los manejadores de ruta te permiten definir múltiples rutas para una ruta. El ejemplo de abajo define dos rutas para solicitudes GET a la ruta /user/:id. La segunda ruta no causará ningún problema, pero nunca se llamará porque la primera ruta finaliza el ciclo solicitud-respuesta.

Este ejemplo muestra una sub-pila de middleware que maneja solicitudes GET a la ruta /user/:id.

app.get(
'/user/:id',
(req, res, next) => {
console.log('ID:', req.params.id);
next();
},
(req, res, next) => {
res.send('User Info');
}
);
// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req, res, next) => {
res.send(req.params.id);
});

Para omitir el resto de las funciones de middleware de una pila de middleware del router, llama a next('route') para pasar el control a la siguiente ruta.

Nota

next('route') solo funcionará en funciones de middleware que fueron cargadas usando las funciones app.METHOD() o router.METHOD().

Este ejemplo muestra una sub-pila de middleware que maneja solicitudes GET a la ruta /user/:id.

app.get(
'/user/:id',
(req, res, next) => {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route');
// otherwise pass the control to the next middleware function in this stack
else next();
},
(req, res, next) => {
// send a regular response
res.send('regular');
}
);
// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req, res, next) => {
res.send('special');
});

El middleware también puede declararse en un array para reutilización.

Este ejemplo muestra un array con una sub-pila de middleware que maneja solicitudes GET a la ruta /user/:id

function logOriginalUrl(req, res, next) {
console.log('Request URL:', req.originalUrl);
next();
}
function logMethod(req, res, next) {
console.log('Request Type:', req.method);
next();
}
const logStuff = [logOriginalUrl, logMethod];
app.get('/user/:id', logStuff, (req, res, next) => {
res.send('User Info');
});

Middleware a nivel de router

El middleware a nivel de router funciona de la misma manera que el middleware a nivel de aplicación, excepto que está vinculado a una instancia de express.Router().

const router = express.Router();

Carga el middleware a nivel de router usando las funciones router.use() y router.METHOD().

El siguiente código de ejemplo replica el sistema de middleware que se muestra arriba para middleware a nivel de aplicación, usando middleware a nivel de router:

index.cjs
const express = require('express');
const app = express();
const router = express.Router();
// a middleware function with no mount path. This code is executed for every request to the router
router.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use(
'/user/:id',
(req, res, next) => {
console.log('Request URL:', req.originalUrl);
next();
},
(req, res, next) => {
console.log('Request Type:', req.method);
next();
}
);
// a middleware sub-stack that handles GET requests to the /user/:id path
router.get(
'/user/:id',
(req, res, next) => {
// if the user ID is 0, skip to the next router
if (req.params.id === '0') next('route');
// otherwise pass control to the next middleware function in this stack
else next();
},
(req, res, next) => {
// render a regular page
res.render('regular');
}
);
// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req, res, next) => {
console.log(req.params.id);
res.render('special');
});
// mount the router on the app
app.use('/', router);

Para omitir el resto de las funciones de middleware del router, llama a next('router') para devolver el control fuera de la instancia del router.

Este ejemplo muestra una sub-pila de middleware que maneja solicitudes GET a la ruta /user/:id.

index.cjs
const express = require('express');
const app = express();
const router = express.Router();
// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
if (!req.headers['x-auth']) return next('router');
next();
});
router.get('/user/:id', (req, res) => {
res.send('hello, user!');
});
// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
res.sendStatus(401);
});

Middleware de manejo de errores

Precaución

El middleware de manejo de errores siempre toma cuatro argumentos. Debes proporcionar cuatro argumentos para identificarlo como una función de middleware de manejo de errores. Incluso si no necesitas usar el objeto next, debes especificarlo para mantener la firma. De lo contrario, el objeto next será interpretado como middleware regular y no podrá manejar errores.

Define las funciones de middleware de manejo de errores de la misma manera que otras funciones de middleware, excepto con cuatro argumentos en lugar de tres, específicamente con la firma (err, req, res, next):

app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});

Para más detalles sobre el middleware de manejo de errores, consulta: Manejo de errores.

Middleware integrado

A partir de la versión 4.x, Express ya no depende de Connect. Las funciones de middleware que anteriormente se incluían con Express ahora están en módulos separados; consulta la lista de funciones de middleware.

Express tiene las siguientes funciones de middleware integradas:

  • express.static sirve assets estáticos como archivos HTML, imágenes, y así sucesivamente.
  • express.json analiza solicitudes entrantes con payloads JSON. NOTA: Disponible con Express 4.16.0+
  • express.urlencoded analiza solicitudes entrantes con payloads URL-encoded. NOTA: Disponible con Express 4.16.0+

Middleware de terceros

Usa middleware de terceros para añadir funcionalidad a las aplicaciones Express.

Instala el módulo de Node.js para la funcionalidad requerida, luego cárgalo en tu aplicación a nivel de aplicación o a nivel de router.

El siguiente ejemplo ilustra la instalación y carga de la función de middleware de análisis de cookies cookie-parser.

Ventana de terminal
npm install cookie-parser
index.cjs
const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');
// load the cookie-parsing middleware
app.use(cookieParser());

Para una lista parcial de funciones de middleware de terceros que se usan comúnmente con Express, consulta: Middleware de terceros.