Files
egutierrez 036c0a8d63 feat(infra): rate limiter token-bucket in-memory + tipos y core funcs
Implementa fase 1 del issue 0016:
- Tipos RateLimiter, RateLimitConfig y RateLimitResult en types/infra/
- rate_limiter_new: constructor con validacion rate/burst > 0
- rate_limiter_check: evalua token bucket por key, calcula Allowed/Remaining/ResetAt/RetryAfter
- rate_limit_headers (pure): construye headers IETF X-RateLimit-* y Retry-After
- rate_limiter_cleanup: goroutine GC de entries inactivas con stop idempotente

Sin dependencias externas (no Redis). sync.Mutex + map. Algoritmo token bucket
estandar con recarga lineal proporcional al tiempo transcurrido.
2026-04-18 17:11:22 +02:00

46 lines
1.3 KiB
Go

package infra
import (
"net/http"
"sync"
"time"
)
// rateLimiterClient mantiene el estado de un bucket para una clave concreta.
type rateLimiterClient struct {
tokens float64
lastSeen time.Time
}
// RateLimiter mantiene el estado token-bucket de todos los clientes en memoria.
// rate son los tokens recargados por segundo, burst es la capacidad maxima del bucket.
// El campo clients es un mapa key -> bucket protegido por mu.
type RateLimiter struct {
rate float64
burst int
mu sync.Mutex
clients map[string]*rateLimiterClient
}
// RateLimitConfig parametriza el middleware de rate limiting.
// KeyFunc extrae la clave del request (nil = IP del cliente).
// CleanupInterval controla la frecuencia del GC de entries inactivas (0 = no GC).
type RateLimitConfig struct {
RequestsPerSecond float64
BurstSize int
KeyFunc func(r *http.Request) string
CleanupInterval time.Duration
}
// RateLimitResult es el resultado de evaluar un request contra el limiter.
// Allowed indica si el request puede pasar.
// Remaining son los tokens restantes en el bucket despues del check.
// ResetAt es el momento en que el bucket vuelve a estar lleno.
// RetryAfter son los segundos hasta que se pueda reintentar (0 si Allowed).
type RateLimitResult struct {
Allowed bool
Remaining int
ResetAt time.Time
RetryAfter float64
}