Clase 01 — Fundamentos de HTTP para APIs
¿Qué es HTTP?
HTTP (HyperText Transfer Protocol) es el protocolo que usan las APIs para comunicarse. Toda API REST funciona sobre HTTP.
Cliente Servidor
│ │
│──── HTTP Request ──────────────►│
│ (método, URL, headers, │
│ body) │
│ │
│◄─── HTTP Response ─────────────│
│ (status code, headers, │
│ body) │
│ │
Versiones de HTTP
| Versión | Año | Características |
|---|---|---|
| HTTP/1.0 | 1996 | Una conexión por petición |
| HTTP/1.1 | 1997 | Keep-alive, pipelining |
| HTTP/2 | 2015 | Multiplexing, compresión headers, binario |
| HTTP/3 | 2022 | QUIC (UDP), menor latencia |
Métodos HTTP (Verbos)
CRUD → HTTP
| CRUD | HTTP | Descripción | Idempotente | Seguro |
|---|---|---|---|---|
| Create | POST | Crear recurso | ❌ No | ❌ No |
| Read | GET | Obtener recurso | ✅ Sí | ✅ Sí |
| Update | PUT | Reemplazar recurso | ✅ Sí | ❌ No |
| Update | PATCH | Actualizar parcial | ❌ No | ❌ No |
| Delete | DELETE | Eliminar recurso | ✅ Sí | ❌ No |
Idempotente: Hacer la misma petición N veces produce el mismo resultado. Seguro: No modifica datos en el servidor.
# CRUD completo con una API de pruebas
API="https://jsonplaceholder.typicode.com"
# CREATE (POST)
curl -s -X POST "$API/posts" \
-H "Content-Type: application/json" \
-d '{"title":"Mi Post","body":"Contenido","userId":1}' | jq '.id'
# READ (GET)
curl -s "$API/posts/1" | jq '{id, title}'
# UPDATE (PUT)
curl -s -X PUT "$API/posts/1" \
-H "Content-Type: application/json" \
-d '{"id":1,"title":"Actualizado","body":"Nuevo contenido","userId":1}' | jq '.'
# PARTIAL UPDATE (PATCH)
curl -s -X PATCH "$API/posts/1" \
-H "Content-Type: application/json" \
-d '{"title":"Solo cambio el título"}' | jq '.'
# DELETE
curl -s -X DELETE "$API/posts/1" -o /dev/null -w "HTTP %{http_code}\n"
URLs y Recursos
Estructura de una URL
https://api.ejemplo.com:443/v2/usuarios/42/posts?limit=10&sort=date
\___/ \_______________/ \_/ \__/ \________/ \____/ \______________/
| | | ver recurso id query params
protocolo host puerto
Convenciones de URLs en APIs REST
# ✅ BUENAS PRÁCTICAS
GET /api/v2/usuarios # Listar usuarios
GET /api/v2/usuarios/42 # Obtener usuario 42
POST /api/v2/usuarios # Crear usuario
PUT /api/v2/usuarios/42 # Actualizar usuario 42
DELETE /api/v2/usuarios/42 # Eliminar usuario 42
GET /api/v2/usuarios/42/posts # Posts del usuario 42
# ❌ MALAS PRÁCTICAS
GET /api/getUsuarios # Verbo en URL
GET /api/usuario/42 # Singular
POST /api/crearUsuario # Verbo en URL
Códigos de Estado HTTP
2xx — Éxito
200 # OK — Éxito general (GET, PUT, PATCH)
201 # Created — Recurso creado (POST)
204 # No Content — Éxito sin body (DELETE)
202 # Accepted — Aceptado, procesando async
4xx — Error del Cliente
400 # Bad Request — Datos inválidos
401 # Unauthorized — No autenticado ("¿Quién sos?")
403 # Forbidden — Sin permisos ("Sé quién sos, pero no podés")
404 # Not Found — Recurso no existe
405 # Method Not Allowed — Método HTTP incorrecto
409 # Conflict — Conflicto (recurso ya existe)
422 # Unprocessable Entity — Validación fallida
429 # Too Many Requests — Rate limit excedido
5xx — Error del Servidor
500 # Internal Server Error — Bug en el servidor
502 # Bad Gateway — Proxy no puede contactar backend
503 # Service Unavailable — Servidor sobrecargado
504 # Gateway Timeout — Proxy timeout al backend
# En DevOps estos son los que te despiertan a las 3am 😅
Script: Verificar status codes
#!/bin/bash
clasificar_codigo() {
local code="$1"
case "$code" in
2[0-9][0-9]) echo "✅ Éxito" ;;
3[0-9][0-9]) echo "↩️ Redirección" ;;
4[0-9][0-9]) echo "❌ Error cliente" ;;
5[0-9][0-9]) echo "💥 Error servidor" ;;
000) echo "🔌 Sin conexión" ;;
*) echo "❓ Desconocido" ;;
esac
}
urls=(
"https://httpbin.org/status/200"
"https://httpbin.org/status/301"
"https://httpbin.org/status/404"
"https://httpbin.org/status/500"
)
printf "%-50s %-6s %s\n" "URL" "CODE" "ESTADO"
for url in "${urls[@]}"; do
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "$url")
estado=$(clasificar_codigo "$code")
printf "%-50s %-6s %s\n" "$url" "$code" "$estado"
done
Headers HTTP
Request Headers (los que envías)
| Header | Propósito | Ejemplo |
|---|---|---|
Content-Type | Formato del body que envías | application/json |
Accept | Formato que querés recibir | application/json |
Authorization | Credenciales/token | Bearer eyJ... |
User-Agent | Identificar al cliente | MiApp/1.0 |
X-Request-ID | Trazabilidad | req-abc-123 |
Response Headers (los que recibís)
| Header | Propósito | Ejemplo |
|---|---|---|
Content-Type | Formato de la respuesta | application/json; charset=utf-8 |
X-RateLimit-Limit | Límite de peticiones | 60 |
X-RateLimit-Remaining | Peticiones restantes | 58 |
Location | URL del recurso creado | /api/users/42 |
Retry-After | Cuándo reintentar (rate limit) | 30 |
# Ver todos los headers que envías
curl -s https://httpbin.org/headers | jq '.headers'
# Ver headers de respuesta
curl -sI https://api.github.com | head -15
HTTPS y TLS
# HTTPS = HTTP + TLS (cifrado)
# Puerto por defecto: 443 (vs 80 para HTTP)
# Verificar certificado SSL
curl -vI https://github.com 2>&1 | grep -E "SSL|TLS|certificate|issuer"
# Ver información del certificado
echo | openssl s_client -servername github.com -connect github.com:443 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates
# ❌ NUNCA en producción
curl -k https://self-signed.example.com # Ignora errores SSL
# ✅ Especificar CA si es necesario
curl --cacert /path/to/ca.pem https://api.interno.com
Ejercicios
- Hacé una petición GET a
https://jsonplaceholder.typicode.com/posts/1y describí cada parte de la respuesta - Ejecutá el CRUD completo (POST, GET, PUT, PATCH, DELETE) contra JSONPlaceholder
- Usá
curl -vpara inspeccionar los headers enviados y recibidos - Creá un script que haga peticiones a diferentes status codes y clasifique cada uno
- Investigá los headers de
X-RateLimitde la API de GitHub