Express

Express

Tutorial Express: Cabeceras HTTP

Aprende a leer y configurar cabeceras HTTP en Express para mejorar seguridad, rendimiento y personalización en tus aplicaciones web.

Aprende Express y certifícate

Lectura de headers

Las cabeceras HTTP contienen información esencial sobre las peticiones que reciben nuestras aplicaciones Express. Desde datos de autenticación hasta preferencias del cliente, las cabeceras proporcionan el contexto necesario para procesar correctamente cada solicitud.

Express facilita el acceso a estas cabeceras a través del objeto req.headers, que contiene todas las cabeceras enviadas por el cliente en formato de objeto JavaScript. Los nombres de las cabeceras se convierten automáticamente a minúsculas para mantener la consistencia, independientemente de cómo las envíe el cliente.

Acceso básico a cabeceras

El método más directo para leer cabeceras es acceder directamente al objeto req.headers:

app.get('/info', (req, res) => {
  // Acceso directo a una cabecera específica
  const userAgent = req.headers['user-agent'];
  const contentType = req.headers['content-type'];
  
  console.log('Navegador del usuario:', userAgent);
  console.log('Tipo de contenido:', contentType);
  
  res.json({
    userAgent,
    contentType
  });
});

Para mayor comodidad, Express también proporciona el método req.get() que permite obtener cabeceras de forma más elegante:

app.get('/client-info', (req, res) => {
  // Método recomendado para obtener cabeceras
  const authorization = req.get('Authorization');
  const acceptLanguage = req.get('Accept-Language');
  const host = req.get('Host');
  
  res.json({
    auth: authorization || 'No autorización',
    language: acceptLanguage || 'No especificado',
    host: host
  });
});

Cabeceras comunes en aplicaciones web

Ciertas cabeceras estándar aparecen frecuentemente en las aplicaciones web y Express las maneja de forma especial:

app.post('/upload', (req, res) => {
  // Cabeceras de contenido
  const contentLength = req.get('Content-Length');
  const contentType = req.get('Content-Type');
  
  // Cabeceras de cliente
  const userAgent = req.get('User-Agent');
  const referer = req.get('Referer');
  
  // Cabeceras de cache
  const cacheControl = req.get('Cache-Control');
  const ifModifiedSince = req.get('If-Modified-Since');
  
  console.log(`Recibiendo ${contentLength} bytes de tipo ${contentType}`);
  
  res.json({
    received: true,
    size: contentLength,
    type: contentType,
    client: userAgent
  });
});

Manejo de cabeceras personalizadas

Las aplicaciones modernas frecuentemente utilizan cabeceras personalizadas para transmitir información específica. Express las trata igual que las cabeceras estándar:

app.get('/api/data', (req, res) => {
  // Cabeceras personalizadas (suelen empezar con X-)
  const apiKey = req.get('X-API-Key');
  const clientVersion = req.get('X-Client-Version');
  const requestId = req.get('X-Request-ID');
  
  // Validación básica
  if (!apiKey) {
    return res.status(401).json({
      error: 'API Key requerida en cabecera X-API-Key'
    });
  }
  
  res.json({
    message: 'Datos procesados correctamente',
    clientVersion: clientVersion || 'Desconocida',
    requestId: requestId
  });
});

Procesamiento condicional basado en cabeceras

Las cabeceras permiten implementar lógica condicional sofisticada en nuestras rutas:

app.get('/content', (req, res) => {
  const acceptHeader = req.get('Accept');
  const acceptLanguage = req.get('Accept-Language');
  
  // Respuesta basada en el tipo de contenido aceptado
  if (acceptHeader && acceptHeader.includes('application/json')) {
    res.json({
      type: 'json',
      message: 'Contenido en formato JSON',
      language: acceptLanguage
    });
  } else if (acceptHeader && acceptHeader.includes('text/html')) {
    res.send(`
      <html>
        <body>
          <h1>Contenido HTML</h1>
          <p>Idioma preferido: ${acceptLanguage || 'No especificado'}</p>
        </body>
      </html>
    `);
  } else {
    res.type('text/plain');
    res.send('Contenido en texto plano');
  }
});

Inspección completa de cabeceras

Para depuración o análisis detallado, podemos examinar todas las cabeceras recibidas:

app.get('/debug/headers', (req, res) => {
  // Obtener todas las cabeceras
  const allHeaders = req.headers;
  
  // Filtrar cabeceras específicas
  const securityHeaders = Object.keys(allHeaders)
    .filter(key => key.startsWith('sec-') || key.includes('security'))
    .reduce((obj, key) => {
      obj[key] = allHeaders[key];
      return obj;
    }, {});
  
  res.json({
    totalHeaders: Object.keys(allHeaders).length,
    securityHeaders,
    commonHeaders: {
      host: req.get('Host'),
      userAgent: req.get('User-Agent'),
      accept: req.get('Accept'),
      connection: req.get('Connection')
    }
  });
});

La lectura eficiente de cabeceras es fundamental para crear aplicaciones Express robustas que puedan adaptarse dinámicamente a las necesidades del cliente y proporcionar respuestas contextualizadas según la información recibida en cada petición.

Configuración de headers

La configuración de cabeceras HTTP en las respuestas es tan importante como su lectura en las peticiones. Express proporciona múltiples métodos para establecer cabeceras que controlan cómo los clientes interpretan y manejan nuestras respuestas, desde aspectos de seguridad hasta optimización de rendimiento.

El objeto res en Express incluye varios métodos para manipular cabeceras de respuesta, siendo res.set() y res.header() los más utilizados. Ambos métodos son equivalentes y permiten establecer cabeceras individuales o múltiples de una sola vez.

Establecimiento básico de cabeceras

La forma más directa de configurar cabeceras es utilizando el método res.set():

app.get('/api/users', (req, res) => {
  // Establecer una cabecera individual
  res.set('Content-Type', 'application/json');
  res.set('X-API-Version', '2.1');
  
  // Establecer múltiples cabeceras con un objeto
  res.set({
    'Cache-Control': 'no-cache, no-store',
    'X-Response-Time': '150ms',
    'X-Powered-By': 'Express-Custom'
  });
  
  res.json({
    users: ['Ana', 'Carlos', 'María'],
    total: 3
  });
});

Cabeceras de tipo de contenido

Express facilita la configuración del tipo de contenido mediante métodos especializados:

app.get('/download/report', (req, res) => {
  // Método específico para Content-Type
  res.type('application/pdf');
  
  // Equivalente a res.set('Content-Type', 'application/pdf')
  res.set('Content-Disposition', 'attachment; filename="reporte.pdf"');
  res.set('Content-Length', '2048576');
  
  // Simular envío de archivo
  res.send('Contenido del PDF...');
});

app.get('/api/xml-data', (req, res) => {
  // Configurar para respuesta XML
  res.type('xml');
  res.set('X-Content-Source', 'database');
  
  const xmlData = `<?xml version="1.0"?>
    <data>
      <item>Elemento 1</item>
      <item>Elemento 2</item>
    </data>`;
  
  res.send(xmlData);
});

Cabeceras de seguridad

Las cabeceras de seguridad son esenciales para proteger las aplicaciones web modernas:

app.get('/secure-page', (req, res) => {
  // Cabeceras de seguridad fundamentales
  res.set({
    'X-Content-Type-Options': 'nosniff',
    'X-Frame-Options': 'DENY',
    'X-XSS-Protection': '1; mode=block',
    'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
    'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline'"
  });
  
  res.json({
    message: 'Página segura cargada',
    timestamp: new Date().toISOString()
  });
});

Cabeceras de cache y rendimiento

La optimización del cache mediante cabeceras mejora significativamente el rendimiento:

app.get('/static-content', (req, res) => {
  // Configuración de cache para contenido estático
  res.set({
    'Cache-Control': 'public, max-age=3600', // 1 hora
    'ETag': '"v1.2.3"',
    'Last-Modified': new Date('2024-01-01').toUTCString()
  });
  
  res.json({
    content: 'Contenido que cambia poco',
    version: '1.2.3'
  });
});

app.get('/dynamic-content', (req, res) => {
  // Configuración para contenido dinámico
  res.set({
    'Cache-Control': 'no-cache, must-revalidate',
    'Pragma': 'no-cache',
    'Expires': '0'
  });
  
  res.json({
    content: 'Datos en tiempo real',
    timestamp: Date.now()
  });
});

Cabeceras condicionales y dinámicas

Las cabeceras pueden configurarse dinámicamente basándose en la lógica de la aplicación:

app.get('/api/content/:type', (req, res) => {
  const contentType = req.params.type;
  const userAgent = req.get('User-Agent');
  
  // Configuración condicional basada en parámetros
  if (contentType === 'mobile') {
    res.set({
      'X-Optimized-For': 'mobile',
      'Cache-Control': 'public, max-age=1800' // 30 minutos
    });
  } else if (contentType === 'desktop') {
    res.set({
      'X-Optimized-For': 'desktop',
      'Cache-Control': 'public, max-age=7200' // 2 horas
    });
  }
  
  // Cabecera basada en el cliente
  if (userAgent && userAgent.includes('Bot')) {
    res.set('X-Robots-Tag', 'index, follow');
  }
  
  res.json({
    type: contentType,
    optimized: true
  });
});

Cabeceras CORS personalizadas

Para aplicaciones que requieren configuración CORS específica:

app.get('/api/public-data', (req, res) => {
  const origin = req.get('Origin');
  
  // Lista de orígenes permitidos
  const allowedOrigins = [
    'https://miapp.com',
    'https://app.midominio.com'
  ];
  
  if (allowedOrigins.includes(origin)) {
    res.set({
      'Access-Control-Allow-Origin': origin,
      'Access-Control-Allow-Credentials': 'true',
      'Access-Control-Expose-Headers': 'X-Total-Count, X-Page-Info'
    });
  }
  
  // Cabeceras informativas para el cliente
  res.set({
    'X-Total-Count': '150',
    'X-Page-Info': 'page=1&limit=10'
  });
  
  res.json({
    data: ['item1', 'item2', 'item3'],
    pagination: { page: 1, total: 150 }
  });
});

Eliminación y modificación de cabeceras

Express también permite eliminar cabeceras existentes cuando sea necesario:

app.get('/custom-response', (req, res) => {
  // Establecer cabeceras iniciales
  res.set({
    'X-Powered-By': 'Express',
    'X-Custom-Header': 'valor-inicial',
    'X-Debug-Info': 'información-sensible'
  });
  
  // Eliminar cabecera específica por seguridad
  res.removeHeader('X-Debug-Info');
  
  // Modificar cabecera existente
  res.set('X-Custom-Header', 'valor-actualizado');
  
  // Verificar si una cabecera está establecida
  const hasPoweredBy = res.get('X-Powered-By');
  
  res.json({
    message: 'Respuesta personalizada',
    hasPoweredBy: !!hasPoweredBy
  });
});

La configuración adecuada de cabeceras HTTP es fundamental para crear aplicaciones Express profesionales que cumplan con estándares de seguridad, rendimiento y compatibilidad, proporcionando a los clientes toda la información necesaria para procesar correctamente las respuestas del servidor.

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 Cabeceras HTTP con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.