package httpserver import ( "net/http" "sync" "time" ) type rateLimiter struct { mu sync.Mutex window time.Duration limit int attempts map[string][]time.Time } func newRateLimiter(limit int, window time.Duration) *rateLimiter { return &rateLimiter{ window: window, limit: limit, attempts: make(map[string][]time.Time), } } func (l *rateLimiter) Allow(key string) bool { now := time.Now() cutoff := now.Add(-l.window) l.mu.Lock() defer l.mu.Unlock() attempts := l.attempts[key] kept := attempts[:0] for _, attempt := range attempts { if attempt.After(cutoff) { kept = append(kept, attempt) } } if len(kept) >= l.limit { l.attempts[key] = kept return false } kept = append(kept, now) l.attempts[key] = kept return true } func authRateLimitKey(r *http.Request) string { return requestIP(r) + ":" + r.URL.Path }