package infra import ( "net" "net/http" "strings" ) // rateLimitClientIP extrae la IP del cliente del request. // Prioridad: X-Forwarded-For (primer valor) > X-Real-IP > RemoteAddr. // Para X-Forwarded-For multi-hop solo se usa el primer IP (cliente original). func rateLimitClientIP(r *http.Request) string { if xff := r.Header.Get("X-Forwarded-For"); xff != "" { parts := strings.Split(xff, ",") ip := strings.TrimSpace(parts[0]) if ip != "" { return ip } } if xri := r.Header.Get("X-Real-IP"); xri != "" { return strings.TrimSpace(xri) } host, _, err := net.SplitHostPort(r.RemoteAddr) if err == nil { return host } return r.RemoteAddr } // RateLimitMiddleware retorna un Middleware que aplica rate limiting por IP del cliente. // Si el request supera el limite responde 429 con headers Retry-After y X-RateLimit-*. // La IP se extrae con prioridad X-Forwarded-For > X-Real-IP > RemoteAddr. func RateLimitMiddleware(rl *RateLimiter) Middleware { return RateLimiterByKey(rl, rateLimitClientIP) }