package middlewares import ( "net" "net/http" "sync" "time" ) type rateEntry struct { Count int ExpiresAt time.Time } var ( rateMu sync.Mutex rateDB = make(map[string]*rateEntry) ) func RateLimit(keyFn func(*http.Request) string, limit int, window time.Duration) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { key := keyFn(r) now := time.Now() rateMu.Lock() e, ok := rateDB[key] if !ok || now.After(e.ExpiresAt) { e = &rateEntry{ Count: 0, ExpiresAt: now.Add(window), } rateDB[key] = e } e.Count++ if e.Count > limit { rateMu.Unlock() http.Error(w, "Too many requests", http.StatusTooManyRequests) return } rateMu.Unlock() next.ServeHTTP(w, r) }) } } // helpers func RateByIP(r *http.Request) string { ip, _, _ := net.SplitHostPort(r.RemoteAddr) return "ip:" + ip } func RateByUser(r *http.Request) string { return "user:" + r.URL.Path // id path’ten okunabilir }