Middleware en Express.js

¿Qué es Middleware en Express.js?

El middleware en Express.js son funciones que tienen acceso al objeto de solicitud (req), al objeto de respuesta (res), y a la siguiente función en el ciclo de solicitud-respuesta. Se utilizan para:

  Ventajas principales

  • Ejecutar código (como logging o validación).
  • Modificar los objetos req y res.
  • Finalizar la solicitud-respuesta (enviar respuestas directamente).
  • Llamar al siguiente middleware en la cadena.

Los middlewares son esenciales para gestionar tareas comunes como autenticación y manejo de errores en aplicaciones Express.

Tipos de Middleware


1Middleware Incorporado en Express
javascript
const express = require('express');
const app = express();

// Middleware para parsear JSON
app.use(express.json());

// Middleware para parsear datos de formularios URL-encoded
app.use(express.urlencoded({ extended: true }));

// Middleware para servir archivos estáticos
app.use(express.static('public'));
2Middleware Personalizado
javascript
// Middleware de autenticación
const autenticarUsuario = (req, res, next) => {
const token = req.headers.authorization;

if (!token) {
  return res.status(401).json({ 
    error: 'No se proporcionó token de autenticación' 
  });
}

try {
  // Verificar token (ejemplo simplificado)
  const usuarioDecodificado = verificarToken(token);
  req.usuario = usuarioDecodificado;
  next();
} catch (error) {
  res.status(403).json({ error: 'Token inválido' });
}
};

// Middleware de registro de solicitudes
const registrarSolicitud = (req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
};

// Middleware de validación de datos
const validarProducto = (req, res, next) => {
const { nombre, precio } = req.body;

if (!nombre || nombre.length < 3) {
  return res.status(400).json({ 
    error: 'El nombre debe tener al menos 3 caracteres' 
  });
}

if (!precio || precio <= 0) {
  return res.status(400).json({ 
    error: 'El precio debe ser un número positivo' 
  });
}

next();
};

// Uso de middleware personalizado
app.post('/productos', 
autenticarUsuario, 
validarProducto, 
(req, res) => {
  // Lógica para crear producto
  res.status(201).json(req.body);
}
);
3Middleware de Terceros

Cors: Gestión de Recursos de Origen Cruzado

javascript
const cors = require('cors');

// Configuración básica
app.use(cors());

// Configuración personalizada
app.use(cors({
origin: 'https://example.com',
methods: ['GET', 'POST', 'PUT', 'DELETE']
}));

Morgan: Registro de Solicitudes HTTP

javascript
const morgan = require('morgan');

// Formatos de registro
app.use(morgan('tiny'));  // Formato conciso
app.use(morgan('combined'));  // Formato detallado
4Manejo de Errores con Middleware
javascript
// Middleware de manejo de errores global
app.use((err, req, res, next) => {
console.error(err.stack);

res.status(500).json({
  mensaje: 'Ocurrió un error interno',
  error: process.env.NODE_ENV === 'development' ? err.message : {}
});
});

// Middleware para rutas no encontradas
app.use((req, res, next) => {
res.status(404).json({
  mensaje: 'Ruta no encontrada'
});
});

Orden de Middleware en Express.js

El orden de los middlewares en Express.js es fundamental para el correcto funcionamiento de la aplicación. Los middleware se ejecutan en el orden en que se declaran. Es importante que cada middleware se coloque en el orden correcto para evitar errores y asegurar que el flujo de la solicitud-respuesta sea el esperado.

Ejemplo de Orden de Middleware:

javascript
// Middleware se ejecutan en orden
app.use(cors());             // Habilitar CORS (Primero)
app.use(express.json());     // Parsear JSON (Luego)
app.use(registrarSolicitud); // Registrar cada solicitud (Después)
  Consideraciones de Rendimiento

  • Minimiza la cantidad de middleware
  • Evita lógica compleja en middleware
  • Usa middleware solo cuando sea necesario
  • Usa next() para pasar al siguiente middleware
  • Maneja errores de manera centralizada
  • Protege tus rutas con middleware de autenticación
  • Utiliza middleware de terceros para funcionalidades comunes