// Package middleware package middleware import ( "net/http" "sync" "time" "golang.org/x/time/rate" ) type RateLimiter struct { visitors map[string]*rate.Limiter mu sync.Mutex rate rate.Limit burst int lastSeen map[string]time.Time } func NewRateLimiter(r rate.Limit, burst int) *RateLimiter { rl := &RateLimiter{ visitors: make(map[string]*rate.Limiter), rate: r, burst: burst, lastSeen: make(map[string]time.Time), } go rl.cleanup() return rl } func (rl *RateLimiter) cleanup() { for { time.Sleep(10 * time.Minute) rl.mu.Lock() for ip, last := range rl.lastSeen { if time.Since(last) > 30*time.Minute { delete(rl.visitors, ip) delete(rl.lastSeen, ip) } } rl.mu.Unlock() } } func (rl *RateLimiter) Middleware() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ip := r.RemoteAddr rl.mu.Lock() limiter, ok := rl.visitors[ip] if !ok { limiter = rate.NewLimiter(rl.rate, rl.burst) rl.visitors[ip] = limiter } rl.lastSeen[ip] = time.Now() rl.mu.Unlock() if !limiter.Allow() { http.Error(w, `{"error":"rate limit exceeded"}`, http.StatusTooManyRequests) return } next.ServeHTTP(w, r) }) } }