Cliente HTTP en Go: técnicas avanzadas para trabajar con solicitudes

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Cliente HTTP en Go: haciendo solicitudes correctamente (nivel avanzado)

El paquete integrado net/http en Go proporciona capacidades potentes, aunque a menudo subestimadas, para crear clientes HTTP robustos. A nivel inicial, los desarrolladores usan http.Get o http.Post, lo cual es conveniente para prototipos rápidos, pero completamente inadecuado para producción. En este artículo analizaremos técnicas avanzadas de configuración del cliente HTTP en Go: ajuste fino de timeouts, gestión del pool de conexiones, creación de cadenas de middleware, implementación de reintentos y manejo adecuado de errores. Aprenderá a escribir código de cliente que soporte cargas elevadas y sea resistente a fallos de red.



1. Configuración de timeouts y pool de conexiones

Un error básico es usar http.DefaultClient. No tiene timeouts y puede quedarse colgado indefinidamente. Para producción, cree siempre su propia instancia de http.Client con una configuración detallada de http.Transport.

package main

import ( "net/http" "time")

func NewClient() *http.Client { transport := &http.Transport{ MaxIdleConns: 100, // Máximo de conexiones inactivas en todo el pool MaxConnsPerHost: 10, // Máximo de conexiones a un mismo host MaxIdleConnsPerHost: 5, // Máximo de conexiones inactivas a un mismo host IdleConnTimeout: 90 * time.Second, // Tiempo de vida de una conexión inactiva DisableCompression: false, // Habilitamos compresión (gzip) }

client := &http.Client{ Transport: transport, Timeout: 30 * time.Second, // Timeout total para toda la solicitud } return client}

Analicemos los parámetros clave:

  • Timeout — límite de tiempo total para ejecutar la solicitud (incluyendo la lectura del cuerpo de la respuesta). Ajústelo según la velocidad esperada de la API (normalmente 10-30 segundos).
  • MaxIdleConns — cantidad de conexiones keep-alive almacenadas en el pool. Para sistemas de alta carga, aumente a 200-500.
  • MaxConnsPerHost — limita la cantidad de conexiones simultáneas a un mismo host. Evita la sobrecarga del servidor.

También se recomienda configurar DialContext con un timeout propio para el establecimiento de la conexión:

transport.DialContext = (&net.Dialer{    Timeout:   5 * time.Second,  // Timeout para el handshake TCP    KeepAlive: 30 * time.Second, // Keep-alive para mantener la conexión}).DialContext


2. Creación de cadenas de middleware para el cliente HTTP

En Go no hay middleware integrado para el cliente, pero podemos implementar fácilmente el patrón "decorador" envolviendo http.RoundTripper. Esto permite añadir logging, métricas, autenticación y otras funciones transversales.

type LoggingRoundTripper struct {    Proxied http.RoundTripper}

func (l *LoggingRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { start := time.Now() resp, err := l.Proxied.RoundTrip(r) duration := time.Since(start)

log.Printf("[%s] %s %s - %d (%v)", r.Method, r.URL.String(), r.Host, resp.StatusCode, duration, ) return resp, err}

// Uso:transport := &LoggingRoundTripper{ Proxied: http.DefaultTransport,}client := &http.Client{Transport: transport}

Se puede crear una cadena de middleware, por ejemplo, para agregar encabezados de autenticación:

type AuthRoundTripper struct {    Proxied http.RoundTripper    Token   string}

func (a *AuthRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { r.Header.Set("Authorization", "Bearer "+a.Token) return a.Proxied.RoundTrip(r)}

// Cadena: Auth → Logging → Transportclient := &http.Client{ Transport: &LoggingRoundTripper{

Blogs

Book Recommendations