53 lines
ratelimit/limiter.go
In-memory per-client rate limiter using a fixed time window.
// Package ratelimit provides per-client request rate limiting for HTTP services.// Each client is identified by an opaque key such as a user ID, remote IP, or API token.// The limiter uses a fixed time window; stale buckets for inactive clients accumulate// and should be evicted by the caller via a periodic cleanup task in production.package ratelimitimport ( "sync" "time")
// Limiter enforces a maximum request count per client key within a fixed time window.type Limiter struct {mu sync.Mutex
limit intwindow time.Duration
buckets map[string]*bucket}
type bucket struct { count intwindowEnd time.Time
}
// New returns a Limiter that allows at most limit requests per window duration per key.func New(limit int, window time.Duration) *Limiter { return &Limiter{limit: limit,
window: window,
buckets: make(map[string]*bucket),}
}
// Allow reports whether the client identified by key is permitted to make a request.// It increments the request count for the current window and returns false// once the count reaches or exceeds the configured limit.func (l *Limiter) Allow(key string) bool {l.mu.Lock()
defer l.mu.Unlock()now := time.Now()
b, ok := l.buckets[key]
if !ok || now.After(b.windowEnd) { l.buckets[key] = &bucket{count: 1, windowEnd: now.Add(l.window)} return true}
b.count++
if b.count > l.limit { return false}
return true}