Usando middleware
Express es un framework web de enrutamiento y middleware que tiene una funcionalidad mínima propia: Una aplicación Express es esencialmente una serie de llamadas a funciones de middleware.
Las funciones Middleware son funciones que tienen acceso al objeto de solicitud (req), el objeto de respuesta (res), y la siguiente función de middleware en el ciclo de solicitud y respuesta de la aplicación. La siguiente función middleware se denota comúnmente por una variable llamada next.
Las funciones de Middleware pueden realizar las siguientes tareas:
- Ejecutar cualquier código.
- Realizar cambios en la solicitud y en los objetos de respuesta.
- Terminar el ciclo de solicitud de respuesta.
- Llame a la siguiente función de middleware en la pila.
Si la función actual de middleware no termina el ciclo de solicitud de 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 utilizar los siguientes tipos de middleware:
- Middleware de nivel de aplicación
- Middleware de nivel superior
- Middleware de manejo de errores
- Middleware incorporado
- Middleware de terceros
Puede cargar middleware de nivel de aplicación y de enrutador con una ruta de montaje opcional. También puede cargar una serie de funciones de middleware juntas, lo que crea un substack del sistema de middleware en un punto de montaje.
Middleware de nivel de aplicación
Vincular middleware a una instancia del objeto de aplicación usando app.use() y app. ETHOD() funciona, donde METHOD es el método HTTP de la petición que la función 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();});import express, { type Express, type Request, type Response, type NextFunction } from 'express';
const app: Express = express();
app.use((req: Request, res: Response, next: NextFunction) => { console.log('Time:', Date.now()); next();});Este ejemplo muestra una función middleware montada en la ruta /user/:id. La función se ejecuta para cualquier tipo de petición
HTTP en la ruta /user/:id.
app.use('/user/:id', (req, res, next) => { console.log('Request Type:', req.method); next();});import { type Request, type Response, type NextFunction } from 'express';
app.use('/user/:id', (req: Request, res: Response, next: NextFunction) => { console.log('Request Type:', req.method); next();});Este ejemplo muestra una ruta y su función manejadora (middleware system). La función maneja peticiones GET a la ruta /user/:id.
app.get('/user/:id', (req, res, next) => { res.send('USER');});import { type Request, type Response, type NextFunction } from 'express';
app.get('/user/:id', (req: Request, res: Response, next: NextFunction) => { res.send('USER');});He aquí un ejemplo de carga de una serie de funciones de middleware en un punto de montaje, con una ruta de montaje.
Ilustra un substack de middleware que imprime la información de la petición para cualquier tipo de petición 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(); });import { type Request, type Response, type NextFunction } from 'express';
app.use( '/user/:id', (req: Request, res: Response, next: NextFunction) => { console.log('Request URL:', req.originalUrl); next(); }, (req: Request, res: Response, next: NextFunction) => { console.log('Request Type:', req.method); next(); });Los manejadores de rutas le permiten definir múltiples rutas para una ruta. El siguiente ejemplo define dos rutas para peticiones GET a la ruta /user/:id. La segunda ruta no causará ningún problema, pero nunca se llamará porque la primera ruta termina el ciclo de solicitud de respuesta.
Este ejemplo muestra un substack de middleware que maneja peticiones 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);});import { type Request, type Response, type NextFunction } from 'express';
app.get( '/user/:id', (req: Request, res: Response, next: NextFunction) => { console.log('ID:', req.params.id); next(); }, (req: Request, res: Response, next: NextFunction) => { res.send('User Info'); });
// handler for the /user/:id path, which prints the user IDapp.get('/user/:id', (req: Request, res: Response, next: NextFunction) => { res.send(req.params.id);});Para omitir el resto de las funciones de middleware desde una pila de middleware de router, llame a next('ruta') para pasar el control a la siguiente ruta.
Note
next('ruta') solo funcionará en funciones de middleware que fueron cargadas usando las funciones
app.METHOD() o router.METHOD().
Este ejemplo muestra un substack de middleware que maneja peticiones 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');});import { type Request, type Response, type NextFunction } from 'express';
app.get( '/user/:id', (req: Request, res: Response, next: NextFunction) => { // 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: Request, res: Response, next: NextFunction) => { // send a regular response res.send('regular'); });
// handler for the /user/:id path, which sends a special responseapp.get('/user/:id', (req: Request, res: Response, next: NextFunction) => { res.send('special');});Middleware también puede ser declarado en una matriz para reusabilidad.
Este ejemplo muestra una matriz con un substack de middleware que maneja peticiones GET en 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');});import { type Request, type Response, type NextFunction } from 'express';
function logOriginalUrl(req: Request, res: Response, next: NextFunction) { console.log('Request URL:', req.originalUrl); next();}
function logMethod(req: Request, res: Response, next: NextFunction) { console.log('Request Type:', req.method); next();}
const logStuff = [logOriginalUrl, logMethod];app.get('/user/:id', logStuff, (req: Request, res: Response, next: NextFunction) => { res.send('User Info');});Middleware de nivel remoto
El middleware Router-level 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();import express from 'express';
const router = express.Router();Carga el middleware a nivel de enrutador usando las funciones router.use() y router.METHOD().
El siguiente código de ejemplo replica el sistema middleware que se muestra arriba para el middleware de nivel de aplicación, mediante el uso de router-level middleware:
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);import express, { type Express, type Request, type Response, type NextFunction } from 'express';
const app: Express = express();const router = express.Router();
// a middleware function with no mount path. This code is executed for every request to the routerrouter.use((req: Request, res: Response, next: NextFunction) => { 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: Request, res: Response, next: NextFunction) => { console.log('Request URL:', req.originalUrl); next(); }, (req: Request, res: Response, next: NextFunction) => { console.log('Request Type:', req.method); next(); });
// a middleware sub-stack that handles GET requests to the /user/:id pathrouter.get( '/user/:id', (req: Request, res: Response, next: NextFunction) => { // 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: Request, res: Response, next: NextFunction) => { // render a regular page res.render('regular'); });
// handler for the /user/:id path, which renders a special pagerouter.get('/user/:id', (req: Request, res: Response, next: NextFunction) => { 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 enrutador, llama a next('router')
para pasar el control de vuelta fuera de la instancia del enrutador.
Este ejemplo muestra un substack de middleware que maneja peticiones 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);});import express, { type Express, type Request, type Response, type NextFunction } from 'express';
const app: Express = express();const router = express.Router();
// predicate the router with a check and bail out when neededrouter.use((req: Request, res: Response, next: NextFunction) => { if (!req.headers['x-auth']) return next('router'); next();});
router.get('/user/:id', (req: Request, res: Response) => { res.send('hello, user!');});
// use the router and 401 anything falling throughapp.use('/admin', router, (req: Request, res: Response) => { res.sendStatus(401);});Middleware de manejo de errores
Middleware manejado por errores siempre toma four argumentos. Debe proporcionar cuatro argumentos para
identificarlo como una función de middleware que maneja errores. Incluso si no necesitas usar el objeto next
, debes especificarlo para mantener la firma. De lo contrario, el objeto siguiente será
interpretado como middleware regular y fallará al manejar errores.
Define las funciones de middleware 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!');});import { type Request, type Response, type NextFunction } from 'express';
app.use((err: Error, req: Request, res: Response, next: NextFunction) => { console.error(err.stack); res.status(500).send('Something broke!');});Para más detalles sobre el middleware de manejo de errores, vea: Gestión de errores.
Middleware incorporado
A partir de la versión 4.x, Express ya no depende de Connect. Las funciones del middleware que anteriormente estaban incluidas con Express están ahora en módulos separados; vea la lista de funciones de middleware.
Express tiene las siguientes funciones de middleware incorporadas:
- express.static serves static assets such as HTML files, images, and so on.
- express.json parses incoming requests with JSON payloads. NOTA: Disponible con Express 4.16.0+
- express.urlencoded parses incoming requests with URL-encoded payloads. NOTA: Disponible con Express 4.16.0+
Middleware de terceros
Utilice middleware de terceros para añadir funcionalidad a aplicaciones Express.
Instale el módulo Node.js para la funcionalidad requerida, luego guárdelo en su aplicación a nivel de aplicación o a nivel de enrutador.
El siguiente ejemplo ilustra la instalación y carga de la función middleware 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());import express, { type Express } from 'express';import cookieParser from 'cookie-parser';
const app: Express = express();
// load the cookie-parsing middlewareapp.use(cookieParser());Para una lista parcial de funciones de middleware de terceros que se utilizan comúnmente con Express, vea: Middleware de terceros.