Saltar al contenido principal

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ónAñoCaracterísticas
HTTP/1.01996Una conexión por petición
HTTP/1.11997Keep-alive, pipelining
HTTP/22015Multiplexing, compresión headers, binario
HTTP/32022QUIC (UDP), menor latencia

Métodos HTTP (Verbos)

CRUD → HTTP

CRUDHTTPDescripciónIdempotenteSeguro
CreatePOSTCrear recurso❌ No❌ No
ReadGETObtener recurso✅ Sí✅ Sí
UpdatePUTReemplazar recurso✅ Sí❌ No
UpdatePATCHActualizar parcial❌ No❌ No
DeleteDELETEEliminar 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)

HeaderPropósitoEjemplo
Content-TypeFormato del body que envíasapplication/json
AcceptFormato que querés recibirapplication/json
AuthorizationCredenciales/tokenBearer eyJ...
User-AgentIdentificar al clienteMiApp/1.0
X-Request-IDTrazabilidadreq-abc-123

Response Headers (los que recibís)

HeaderPropósitoEjemplo
Content-TypeFormato de la respuestaapplication/json; charset=utf-8
X-RateLimit-LimitLímite de peticiones60
X-RateLimit-RemainingPeticiones restantes58
LocationURL del recurso creado/api/users/42
Retry-AfterCuá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

  1. Hacé una petición GET a https://jsonplaceholder.typicode.com/posts/1 y describí cada parte de la respuesta
  2. Ejecutá el CRUD completo (POST, GET, PUT, PATCH, DELETE) contra JSONPlaceholder
  3. Usá curl -v para inspeccionar los headers enviados y recibidos
  4. Creá un script que haga peticiones a diferentes status codes y clasifique cada uno
  5. Investigá los headers de X-RateLimit de la API de GitHub