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:
- Middleware a nivel de aplicación
- Middleware a nivel de router
- Middleware de manejo de errores
- Middleware integrado
- Middleware de terceros
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.
const express = require('express');const app = express();
app.use((req, res, next) => { console.log('Time:', Date.now()); next();});import express from '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 IDapp.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 responseapp.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:
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 routerrouter.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 pathrouter.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 pathrouter.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 pagerouter.get('/user/:id', (req, res, next) => { console.log(req.params.id); res.render('special');});
// mount the router on the appapp.use('/', router);import express from 'express';
const app = express();const router = express.Router();
// a middleware function with no mount path. This code is executed for every request to the routerrouter.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 pathrouter.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 pathrouter.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 pagerouter.get('/user/:id', (req, res, next) => { console.log(req.params.id); res.render('special');});
// mount the router on the appapp.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.
const express = require('express');const app = express();const router = express.Router();
// predicate the router with a check and bail out when neededrouter.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 throughapp.use('/admin', router, (req, res) => { res.sendStatus(401);});import express from 'express';
const app = express();const router = express.Router();
// predicate the router with a check and bail out when neededrouter.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 throughapp.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.
npm install cookie-parseryarn add cookie-parserpnpm add cookie-parserbun add cookie-parserconst express = require('express');const app = express();const cookieParser = require('cookie-parser');
// load the cookie-parsing middlewareapp.use(cookieParser());import express from 'express';import cookieParser from 'cookie-parser';
const app = express();
// load the cookie-parsing middlewareapp.use(cookieParser());Para una lista parcial de funciones de middleware de terceros que se usan comúnmente con Express, consulta: Middleware de terceros.