Files
cairnquire/apps/server/internal/httpserver/rate_limit.go
2026-05-28 08:35:50 -04:00

50 lines
871 B
Go

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
}