Cabeceras HTTP

Fundamentos Security Notes Jan 9, 2026 HTTP
http headers metadata request response

Definición

Las cabeceras HTTP son pares clave-valor incluidos en peticiones y respuestas HTTP para proporcionar metadatos sobre el mensaje. Controlan comportamiento, habilitan características y transmiten información sobre contenido, autenticación, cacheo, codificación y más.

Las cabeceras se dividen en cuatro categorías:

  1. Cabeceras de Petición - Enviadas por clientes (ej. Authorization, Accept, User-Agent)
  2. Cabeceras de Respuesta - Enviadas por servidores (ej. Content-Type, Cache-Control, ETag)
  3. Cabeceras de Representación - Describen los datos del cuerpo (ej. Content-Length, Content-Encoding)
  4. Cabeceras Personalizadas - Específicas de aplicación (ej. X-RateLimit-Remaining, X-Request-ID)

Las cabeceras HTTP están definidas en RFC 7231 y son fundamentales para APIs REST, seguridad web y optimización de rendimiento.

Ejemplo

Cabeceras de Petición:

GET /api/users/123 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Accept-Language: en-US,en;q=0.9
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Cache-Control: no-cache

Cabeceras de Respuesta:

HTTP/1.1 200 OK
Date: Thu, 09 Jan 2026 10:30:00 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 142
Cache-Control: max-age=3600, public
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1736421000
Access-Control-Allow-Origin: https://example.com
Strict-Transport-Security: max-age=31536000; includeSubDomains

{
  "id": 123,
  "name": "Alice Smith"
}

Ejemplo de Código

JavaScript (Fetch API):

// Establecer Cabeceras de Petición
const fetchUser = async (userId) => {
  const response = await fetch(`https://api.example.com/users/${userId}`, {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer YOUR_TOKEN',
      'Accept': 'application/json',
      'Accept-Language': 'en-US',
      'X-Request-ID': crypto.randomUUID(),
      'If-None-Match': '"33a64df551425fcc55e4d42a148795d9f25f89d4"'
    }
  });

  // Leer Cabeceras de Respuesta
  console.log('Content-Type:', response.headers.get('Content-Type'));
  console.log('ETag:', response.headers.get('ETag'));
  console.log('Rate Limit:', response.headers.get('X-RateLimit-Remaining'));

  // Iterar todas las cabeceras
  for (const [key, value] of response.headers) {
    console.log(`${key}: ${value}`);
  }

  // Verificar si está cacheado (304 Not Modified)
  if (response.status === 304) {
    console.log('Using cached version');
    return null;
  }

  return await response.json();
};

// Cabeceras Personalizadas en Petición POST
const createUser = async (userData) => {
  const response = await fetch('https://api.example.com/users', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_TOKEN',
      'X-Idempotency-Key': crypto.randomUUID(), // Prevenir peticiones duplicadas
      'X-Client-Version': '1.2.3'
    },
    body: JSON.stringify(userData)
  });

  return await response.json();
};

Python (librería requests):

import requests
import uuid

# Establecer Cabeceras de Petición
def fetch_user(user_id):
    headers = {
        'Authorization': 'Bearer YOUR_TOKEN',
        'Accept': 'application/json',
        'Accept-Language': 'en-US',
        'X-Request-ID': str(uuid.uuid4()),
        'If-None-Match': '"33a64df551425fcc55e4d42a148795d9f25f89d4"'
    }

    response = requests.get(
        f'https://api.example.com/users/{user_id}',
        headers=headers
    )

    # Leer Cabeceras de Respuesta
    print(f"Content-Type: {response.headers.get('Content-Type')}")
    print(f"ETag: {response.headers.get('ETag')}")
    print(f"Rate Limit: {response.headers.get('X-RateLimit-Remaining')}")

    # Iterar todas las cabeceras
    for key, value in response.headers.items():
        print(f"{key}: {value}")

    # Verificar si está cacheado (304 Not Modified)
    if response.status_code == 304:
        print('Using cached version')
        return None

    response.raise_for_status()
    return response.json()

# Cabeceras Personalizadas en Petición POST
def create_user(user_data):
    headers = {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer YOUR_TOKEN',
        'X-Idempotency-Key': str(uuid.uuid4()),
        'X-Client-Version': '1.2.3'
    }

    response = requests.post(
        'https://api.example.com/users',
        json=user_data,
        headers=headers
    )

    response.raise_for_status()
    return response.json()

Diagrama

graph TB
    subgraph "Cabeceras de Petición"
        RH1[Authorization]
        RH2[Accept]
        RH3[Content-Type]
        RH4[User-Agent]
        RH5[If-None-Match]
    end

    subgraph "Cabeceras de Respuesta"
        RES1[Content-Type]
        RES2[Cache-Control]
        RES3[ETag]
        RES4[X-RateLimit-*]
        RES5[Access-Control-*]
    end

    subgraph "Cabeceras de Seguridad"
        SEC1[Strict-Transport-Security]
        SEC2[Content-Security-Policy]
        SEC3[X-Frame-Options]
        SEC4[X-Content-Type-Options]
    end

    Client -->|Enviar Petición| RH1
    Client -->|Enviar Petición| RH2
    Client -->|Enviar Petición| RH3
    Client -->|Enviar Petición| RH4
    Client -->|Enviar Petición| RH5

    Server -->|Enviar Respuesta| RES1
    Server -->|Enviar Respuesta| RES2
    Server -->|Enviar Respuesta| RES3
    Server -->|Enviar Respuesta| RES4
    Server -->|Enviar Respuesta| RES5

    Server -->|Seguridad| SEC1
    Server -->|Seguridad| SEC2
    Server -->|Seguridad| SEC3
    Server -->|Seguridad| SEC4

Notas de Seguridad

SECURITY NOTES

CRÍTICO - …

Configuración y Validación:

  • Nunca exponer datos sensibles en cabeceras que puedan ser registradas.
  • Validar todas las cabeceras de entrada para prevenir ataques de inyección de cabeceras.
  • Usar HTTPS para encriptar cabeceras en tránsito.

Monitoreo y Protección:

  • Establecer cabeceras de seguridad como Strict-Transport-Security, Content-Security-Policy y X-Frame-Options.
  • Nunca confiar en cabeceras proporcionadas por el cliente para decisiones de seguridad sin validación.
  • Sanitizar cabeceras personalizadas para prevenir inyección de logs.
  • Evitar reflejar entrada de usuario en cabeceras de respuesta sin codificación.

Analogía

Piensa en las cabeceras HTTP como etiquetas de envío en un paquete:

  • Cabeceras de Petición → Instrucciones de envío (“Manejar con cuidado”, “Frágil”)
  • Cabeceras de Respuesta → Información de recibo de devolución (número de rastreo, fecha de entrega)
  • Content-Type → Qué hay dentro de la caja (libros, electrónicos, comida)
  • Authorization → Firma demostrando que tienes permiso para enviar/recibir

El paquete (cuerpo) es el contenido real, pero las etiquetas (cabeceras) controlan cómo se maneja.

Mejores Prácticas

  1. Establecer Cabeceras Requeridas - Host, Content-Type, Authorization cuando sea necesario
  2. Usar Cabeceras Estándar - Seguir especificaciones RFC para cabeceras comunes
  3. Incluir Cabeceras de Seguridad - HSTS, CSP, X-Frame-Options, X-Content-Type-Options
  4. Habilitar Cacheo - Usar Cache-Control, ETag, Last-Modified para rendimiento
  5. Añadir Info de Rate Limit - Incluir cabeceras X-RateLimit-* para clientes de API
  6. Establecer Cabeceras CORS - Configurar Access-Control-* para peticiones cross-origin
  7. Evitar Prefijo X- Personalizado - Práctica moderna usa nombres estándar sin X- (RFC 6648)
  8. Validar Cabeceras de Entrada - Sanitizar y validar todas las cabeceras entrantes
  9. Registrar Request IDs - Usar X-Request-ID para rastrear peticiones entre servicios

Errores Comunes

  • Content-Type Faltante - No especificar el formato del cuerpo en peticiones/respuestas
  • Formato de Authorization Incorrecto - Usar Token abc en lugar de Bearer abc
  • Exponer Secretos - Registrar o cachear cabeceras que contienen tokens
  • Sin Cabeceras de Seguridad - No establecer HSTS, CSP o X-Frame-Options
  • Sensibilidad a Mayúsculas - Tratar cabeceras como sensibles a mayúsculas (son insensibles a mayúsculas)
  • Inyección de Cabeceras - No sanitizar entrada de usuario que va en cabeceras
  • Cachear Datos Sensibles - Establecer Cache-Control: public en endpoints autenticados
  • Confiar en Cabeceras Forwarded - Usar X-Forwarded-For sin validación

Estándares & RFCs

Términos Relacionados