package main import ( "sync" "time" ) // rateLimiter is a minimal in-memory fixed-window limiter keyed by string // (bearer-token subject for the TMDB proxy). It blunts runaway clients abusing // the shared API key; it is not a full DoS defense. type rateLimiter struct { mu sync.Mutex limit int window time.Duration counts map[string]rateEntry } type rateEntry struct { windowStart time.Time count int } func newRateLimiter(limit int, per time.Duration) *rateLimiter { return &rateLimiter{limit: limit, window: per, counts: map[string]rateEntry{}} } func (r *rateLimiter) allow(key string) bool { r.mu.Lock() defer r.mu.Unlock() now := time.Now() e, ok := r.counts[key] if !ok || now.Sub(e.windowStart) >= r.window { // Occasionally garbage-collect stale keys so the map stays bounded. if len(r.counts) > 10_000 { for k, v := range r.counts { if now.Sub(v.windowStart) >= r.window { delete(r.counts, k) } } } r.counts[key] = rateEntry{windowStart: now, count: 1} return true } e.count++ r.counts[key] = e return e.count <= r.limit }