🌐 HTTP de punta a punta
Cómo funciona el protocolo que mueve la web: peticiones, respuestas, métodos, códigos de estado, cabeceras, caché y cookies.
HTTP de punta a punta
HTTP (HyperText Transfer Protocol) es el protocolo de aplicación que mueve la web. Cuando tu backend recibe una petición o cuando tu frontend hace un fetch, todo ocurre sobre HTTP. Entenderlo a fondo — no de memoria, sino de razonamiento — es la base de todo ingeniero web.
Anatomía de una petición
Toda petición HTTP tiene la misma estructura:
MÉTODO RUTA HTTP/versión ← línea de inicio (request line)
Host: api.midominio.com ← cabeceras (headers)
Authorization: Bearer xxx
Content-Type: application/json
{"nombre": "Ana"} ← cuerpo (body, opcional)
Lo que ves con curl:
curl -i https://api.github.com/users/torvalds
HTTP/2 200
server: GitHub.com
content-type: application/json; charset=utf-8
cache-control: public, max-age=60, s-maxage=60
etag: W/"3d5... "
{
"login": "torvalds",
"name": "Linus Torvalds",
"public_repos": 7
}
💡 La primera línea de la respuesta es la línea de estado:
HTTP/2 200. El número es el código de estado; no memorices los 60, entiende las familias (abajo).
Métodos HTTP
Los métodos (verbos) expresan intención, no implementación:
| Método | Intención | Idempotente | Seguro |
|---|---|---|---|
GET |
Obtener un recurso | ✅ | ✅ |
POST |
Crear / procesar | ❌ | ❌ |
PUT |
Reemplazar completo | ✅ | ❌ |
PATCH |
Modificar parcial | ❌ | ❌ |
DELETE |
Eliminar | ✅ | ❌ |
HEAD |
Solo cabeceras | ✅ | ✅ |
OPTIONS |
Preflight CORS | ✅ | ✅ |
- Idempotente: repetir la misma petición N veces produce el mismo resultado que una vez. Esto es lo que permite retries seguros.
- Seguro: no modifica el estado del servidor (solo lectura).
curl -X POST https://api.midominio.com/usuarios \
-H "Content-Type: application/json" \
-d '{"nombre": "Ana", "email": "ana@x.com"}'
Códigos de estado por familia
| Familia | Significado | Ejemplos |
|---|---|---|
| 1xx | Informativo | 100 Continue, 101 Switching Protocols |
| 2xx | Éxito | 200 OK, 201 Created, 202 Accepted, 204 No Content |
| 3xx | Redirección | 301 Moved Permanently, 302 Found, 304 Not Modified |
| 4xx | Error del cliente | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable Entity, 429 Too Many Requests |
| 5xx | Error del servidor | 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout |
Errores que se confunden:
- 401 = no autenticado (¿quién eres?). 403 = autenticado pero sin permiso (¿puedes?). Devuelve
401solo si la petición no tiene credenciales válidas. - 404 vs 403: si no quieres filtrar qué recursos existen, devuelve
404para ambos (evita enumeración). - 422 vs 400:
422para errores de validación semántica (el body es JSON válido pero el email no lo es);400para sintaxis inválida. - 429 para rate limiting (con la cabecera
Retry-After).
Cabeceras esenciales
| Cabecera | Propósito |
|---|---|
Content-Type |
Formato del body (application/json, multipart/form-data…) |
Accept |
Formato que el cliente acepta; base de la negociación de contenido |
Authorization |
Credenciales (Bearer <token>, Basic …) |
Cache-Control |
Política de caché (no-store, max-age=60, private) |
ETag |
Identificador de versión del recurso para validación de caché |
Location |
Dónde está el recurso creado (junto a 201) |
Set-Cookie |
Crear una cookie en el cliente |
Retry-After |
Cuándo reintentar (junto a 429/503) |
CORS: Access-Control-Allow-Origin |
Quién puede llamar a tu API desde el navegador |
X-Request-ID |
Correlacionar una petición entre logs/servicios |
Caché HTTP
La caché HTTP tiene dos capas:
- Caché del navegador (privada): controlada por
Cache-Control: private/max-age. - Caché compartida (CDN, proxy): controlada por
s-maxage/public.
Dos estrategias:
Cache-Control: max-age=3600 # reutilizar sin preguntar (1h)
ETag: "v42" # validación: preguntar si cambió
La validación con ETag:
- Cliente manda
If-None-Match: "v42". - Si no cambió →
304 Not Modified(sin body, barato). - Si cambió →
200con el body nuevo.
💡 La caché es tu primera línea de rendimiento: una página cacheada no toca ni la red ni la base de datos. Pero cuidado: nunca cachear datos personales (
Cache-Control: privateono-store).
Cookies y sesiones
Las cookies son datos que el servidor le pide al navegador guardar y reenviar en cada petición.
Set-Cookie: sesion=abc123; HttpOnly; Secure; SameSite=Lax; Max-Age=86400
Atributos importantes:
| Atributo | Qué hace |
|---|---|
HttpOnly |
Inaccesible desde JavaScript (protege contra XSS) |
Secure |
Solo se envía por HTTPS |
SameSite=Lax/Strict/None |
Controla envío en peticiones cross-site (mitiga CSRF) |
Max-Age / Expires |
Caducidad |
Domain/Path |
Alcance de la cookie |
HTTP/2 y HTTP/3
- HTTP/1.1: una conexión TCP → una petición a la vez (head-of-line blocking). Se palió con connection pooling y pipelining.
- HTTP/2: multiplexing sobre la misma conexión TCP (varias peticiones en paralelo), compresión de cabeceras (HPACK), priorización y server push. Requiere TLS en la práctica.
- HTTP/3: cambia TCP por QUIC (sobre UDP). Elimina el bloqueo de head-of-line a nivel de transporte y reduce la latencia en redes con pérdida de paquetes.
Implicación para tu backend: mantener HTTP/2/3 con Nginx y TLS es la línea base del rendimiento moderno. Ver Nginx de verdad.
HTTPS: lo que cifra
HTTPS = HTTP sobre TLS. El handshake TLS:
- El cliente pide la conexión segura.
- El servidor envía su certificado (cadena de confianza hacia una CA).
- Ambos negocian la clave de sesión (clave simétrica, tras un intercambio asimétrico).
- A partir de ahí, todo cifrado.
Sin TLS, un atacante en el medio (MITM) puede leer y modificar todo. En 2026, no hay excusa: certificados gratis y automáticos con Let’s Encrypt.
Para profundizar
- MDN — HTTP: la referencia completa en español.
- restfulapi.net: buenas prácticas de diseño HTTP/REST.
- Cloudflare Learning — HTTP: protocolo y TLS explicados.
- Ruta de recursos: Backend — visión general.