package ratelimit import ( "sync" "time" ) // IPWindow limits how often the same IP may perform an action. type IPWindow struct { mu sync.Mutex hits map[string][]time.Time max int window time.Duration } func NewIPWindow(max int, window time.Duration) *IPWindow { return &IPWindow{ hits: make(map[string][]time.Time), max: max, window: window, } } // Allow returns false if this IP has exceeded the limit. func (w *IPWindow) Allow(ip string) bool { if ip == "" { ip = "unknown" } now := time.Now() cutoff := now.Add(-w.window) w.mu.Lock() defer w.mu.Unlock() ts := w.hits[ip] kept := ts[:0] for _, t := range ts { if t.After(cutoff) { kept = append(kept, t) } } if len(kept) >= w.max { w.hits[ip] = kept return false } kept = append(kept, now) w.hits[ip] = kept return true }