fix: rate limiter memory pruning in Check(), services error leakage replaced with generic messages

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-08-22 00:34:51 +01:00
co-authored by Sisyphus
parent 37f6723d9e
commit d03ce79c19
2 changed files with 14 additions and 3 deletions
+4 -2
View File
@@ -523,7 +523,8 @@ func ServicesEligibleForUserHandler(w http.ResponseWriter, r *http.Request) {
return
}
if err != nil {
http.Error(w, "Failed to get user data: "+err.Error(), http.StatusInternalServerError)
log.Printf("Failed to get user data for %s: %v", userID, err)
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
@@ -550,7 +551,8 @@ func ServicesEligibleForUserHandler(w http.ResponseWriter, r *http.Request) {
rows, err := db.Conn.Query(r.Context(), query)
if err != nil {
http.Error(w, "Failed to fetch services: "+err.Error(), http.StatusInternalServerError)
log.Printf("Failed to fetch services: %v", err)
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
defer rows.Close()
+10 -1
View File
@@ -50,7 +50,7 @@ func NewProgressiveRateLimiter() *ProgressiveRateLimiter {
// Check returns the delay in milliseconds. Returns 0 if no delay needed.
// Strategy:
// - Count requests in last 5 seconds (burst): allow up to 30
// - Count requests in last 60 seconds (sustained): allow up to 60
// - Count requests in last 60 seconds (sustained): allow up to 120
// - Only delay when BOTH windows are exceeded (high sustained rate with recent bursts)
// - Progressive: once throttled, delay increases with sustained rate
func (prl *ProgressiveRateLimiter) Check(ip string) (delayMs int) {
@@ -68,6 +68,15 @@ func (prl *ProgressiveRateLimiter) Check(ip string) (delayMs int) {
state.timestamps = append(state.timestamps, now)
cutoff := now.Add(-60 * time.Second)
pruned := state.timestamps[:0]
for _, t := range state.timestamps {
if t.After(cutoff) {
pruned = append(pruned, t)
}
}
state.timestamps = pruned
burstCutoff := now.Add(-5 * time.Second)
burstCount := 0
for _, t := range state.timestamps {