Express

Express

Tutorial Express: Middlewares built-in

Aprende a usar los middlewares integrados express.json() y express.static() para gestionar JSON y servir archivos estáticos en Express.

Aprende Express y certifícate

express.json()

El middleware express.json() es uno de los middlewares integrados más utilizados en Express, diseñado específicamente para procesar datos JSON enviados en el cuerpo de las peticiones HTTP. Este middleware analiza automáticamente el contenido JSON y lo convierte en un objeto JavaScript accesible a través de req.body.

Configuración básica

Para habilitar el procesamiento de JSON en tu aplicación Express, simplemente registra el middleware utilizando app.use():

import express from 'express';

const app = express();

// Habilitar el procesamiento de JSON
app.use(express.json());

app.post('/usuarios', (req, res) => {
  console.log(req.body); // Objeto JavaScript parseado
  res.json({ mensaje: 'Usuario recibido', datos: req.body });
});

app.listen(3000);

Una vez configurado, cualquier petición con Content-Type application/json será procesada automáticamente. El middleware verifica el tipo de contenido y solo procesa aquellas peticiones que contengan JSON válido.

Opciones de configuración

El middleware express.json() acepta un objeto de opciones que permite personalizar su comportamiento según las necesidades de tu aplicación:

app.use(express.json({
  limit: '10mb',        // Tamaño máximo del cuerpo
  strict: true,         // Solo acepta arrays y objetos
  type: 'application/json' // Tipos MIME a procesar
}));

La opción limit es especialmente importante para controlar el tamaño máximo de los datos que acepta tu servidor. Por defecto, Express establece un límite de 100kb, pero puedes ajustarlo según tus necesidades:

// Para APIs que manejan archivos pequeños codificados en base64
app.use(express.json({ limit: '50mb' }));

// Para APIs con restricciones estrictas de tamaño
app.use(express.json({ limit: '1kb' }));

Manejo de errores de parsing

Cuando el middleware encuentra JSON malformado o datos que exceden el límite establecido, genera automáticamente un error. Es importante implementar un manejador de errores para gestionar estas situaciones:

app.use(express.json());

app.post('/datos', (req, res) => {
  // Si llegamos aquí, el JSON es válido
  res.json({ 
    recibido: true, 
    datos: req.body 
  });
});

// Manejador de errores para JSON inválido
app.use((err, req, res, next) => {
  if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
    return res.status(400).json({ 
      error: 'JSON malformado',
      mensaje: 'Verifica la sintaxis del JSON enviado'
    });
  }
  next(err);
});

Configuración selectiva por rutas

En aplicaciones complejas, es posible que no todas las rutas necesiten procesar JSON. Puedes aplicar el middleware de forma selectiva a rutas específicas:

const app = express();

// Rutas que NO procesan JSON
app.get('/status', (req, res) => {
  res.json({ estado: 'activo' });
});

// Aplicar express.json() solo a rutas específicas
const apiRouter = express.Router();
apiRouter.use(express.json());

apiRouter.post('/usuarios', (req, res) => {
  // req.body disponible aquí
  res.json({ usuario: req.body });
});

apiRouter.put('/usuarios/:id', (req, res) => {
  // req.body también disponible aquí
  res.json({ 
    id: req.params.id, 
    datosActualizados: req.body 
  });
});

app.use('/api', apiRouter);

Validación de tipos de contenido

El middleware express.json() incluye validación automática del Content-Type. Solo procesa peticiones que declaren explícitamente contenido JSON:

app.use(express.json({
  type: ['application/json', 'application/vnd.api+json']
}));

app.post('/flexible', (req, res) => {
  // Acepta tanto application/json como application/vnd.api+json
  res.json({ 
    tipoRecibido: req.get('Content-Type'),
    datos: req.body 
  });
});

Esta validación automática previene errores comunes donde el cliente envía datos en un formato diferente al esperado, proporcionando una capa adicional de seguridad y consistencia en tu API.

express.static()

El middleware express.static() permite servir archivos estáticos directamente desde el sistema de archivos del servidor. Este middleware integrado es fundamental para entregar recursos como imágenes, hojas de estilo CSS, archivos JavaScript del cliente, documentos PDF y cualquier otro contenido estático que tu aplicación web necesite.

Configuración básica

Para servir archivos estáticos, especifica el directorio que contiene los recursos utilizando express.static():

import express from 'express';
import path from 'path';

const app = express();

// Servir archivos desde el directorio 'public'
app.use(express.static('public'));

app.listen(3000);

Con esta configuración, los archivos ubicados en el directorio public serán accesibles directamente a través de URLs. Por ejemplo, si tienes un archivo public/images/logo.png, estará disponible en http://localhost:3000/images/logo.png.

Rutas virtuales y prefijos

Puedes crear rutas virtuales que no corresponden directamente con la estructura de directorios del servidor. Esto es útil para organizar mejor las URLs de tu aplicación:

// Servir archivos con un prefijo virtual
app.use('/assets', express.static('public'));

// Ahora 'public/css/styles.css' está disponible en '/assets/css/styles.css'
app.use('/media', express.static('uploads'));

// Los archivos de 'uploads' se sirven bajo '/media'

Esta aproximación te permite mantener una estructura de URLs limpia independientemente de cómo organices los archivos en el servidor.

Múltiples directorios estáticos

Express permite configurar múltiples directorios estáticos, buscando archivos en el orden en que se registran los middlewares:

// Express buscará archivos en este orden:
app.use(express.static('public'));
app.use(express.static('assets'));
app.use(express.static('uploads'));

// Si 'style.css' existe en 'public' y 'assets', 
// se servirá desde 'public' (primer directorio registrado)

Opciones de configuración avanzadas

El middleware express.static() acepta un objeto de opciones que permite personalizar su comportamiento:

app.use('/static', express.static('public', {
  maxAge: '1d',           // Cache por 1 día
  etag: true,             // Habilitar ETags
  lastModified: true,     // Incluir Last-Modified header
  index: ['index.html', 'index.htm'], // Archivos índice
  dotfiles: 'ignore'      // Ignorar archivos que empiecen con punto
}));

La opción maxAge es especialmente importante para el rendimiento, ya que permite que los navegadores cacheen los recursos estáticos:

// Configuración para diferentes tipos de contenido
app.use('/css', express.static('public/css', { maxAge: '7d' }));
app.use('/js', express.static('public/js', { maxAge: '7d' }));
app.use('/images', express.static('public/images', { maxAge: '30d' }));

Seguridad y archivos ocultos

Por defecto, Express ignora los archivos ocultos (que comienzan con punto) por razones de seguridad. Puedes controlar este comportamiento:

// Permitir archivos ocultos específicos
app.use(express.static('public', {
  dotfiles: 'allow'
}));

// Denegar explícitamente archivos ocultos
app.use(express.static('public', {
  dotfiles: 'deny'
}));

Rutas absolutas y relativas

Para evitar problemas con rutas relativas, especialmente en aplicaciones desplegadas, utiliza rutas absolutas:

import { fileURLToPath } from 'url';
import { dirname, join } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Ruta absoluta recomendada
app.use(express.static(join(__dirname, 'public')));

// Múltiples directorios con rutas absolutas
app.use('/uploads', express.static(join(__dirname, 'user-uploads')));
app.use('/docs', express.static(join(__dirname, 'documentation')));

Manejo de errores y archivos no encontrados

Cuando un archivo estático no existe, express.static() simplemente pasa el control al siguiente middleware sin generar un error. Esto permite implementar fallbacks personalizados:

// Intentar servir desde múltiples ubicaciones
app.use(express.static('public'));
app.use(express.static('backup-assets'));

// Fallback para archivos no encontrados
app.use('/assets/*', (req, res) => {
  res.status(404).json({ 
    error: 'Recurso no encontrado',
    ruta: req.path 
  });
});

Integración con aplicaciones SPA

Para aplicaciones de una sola página (SPA), es común necesitar que todas las rutas no estáticas redirijan al archivo principal:

// Servir archivos estáticos primero
app.use(express.static('dist'));

// API routes
app.use('/api', apiRouter);

// Fallback para SPA - debe ir al final
app.get('*', (req, res) => {
  res.sendFile(join(__dirname, 'dist', 'index.html'));
});

Esta configuración permite que tu aplicación SPA maneje el enrutamiento del lado del cliente mientras mantiene el acceso a los recursos estáticos necesarios.

Aprende Express online

Otras lecciones de Express

Accede a todas las lecciones de Express y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a Express y certifícate

Ejercicios de programación de Express

Evalúa tus conocimientos de esta lección Middlewares built-in con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.