Skip to content

Commit fa0620f

Browse files
committed
fix Rate limiter disallows fractional rates
1 parent 6067257 commit fa0620f

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

middleware/rate_limiter.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package middleware
55

66
import (
7+
"math"
78
"net/http"
89
"sync"
910
"time"
@@ -215,7 +216,7 @@ func NewRateLimiterMemoryStoreWithConfig(config RateLimiterMemoryStoreConfig) (s
215216
store.expiresIn = DefaultRateLimiterMemoryStoreConfig.ExpiresIn
216217
}
217218
if config.Burst == 0 {
218-
store.burst = int(config.Rate)
219+
store.burst = int(math.Max(1, math.Ceil(float64(config.Rate))))
219220
}
220221
store.visitors = make(map[string]*Visitor)
221222
store.timeNow = time.Now

middleware/rate_limiter_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,33 @@ func TestNewRateLimiterMemoryStore(t *testing.T) {
410410
}
411411
}
412412

413+
func TestRateLimiterMemoryStore_FractionalRateDefaultBurst(t *testing.T) {
414+
store := NewRateLimiterMemoryStoreWithConfig(RateLimiterMemoryStoreConfig{
415+
Rate: 0.5, // fractional rate should get a burst of at least 1
416+
})
417+
418+
base := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
419+
store.timeNow = func() time.Time {
420+
return base
421+
}
422+
423+
allowed, err := store.Allow("user")
424+
assert.NoError(t, err)
425+
assert.True(t, allowed, "first request should not be blocked")
426+
427+
allowed, err = store.Allow("user")
428+
assert.NoError(t, err)
429+
assert.False(t, allowed, "burst token should be consumed immediately")
430+
431+
store.timeNow = func() time.Time {
432+
return base.Add(2 * time.Second)
433+
}
434+
435+
allowed, err = store.Allow("user")
436+
assert.NoError(t, err)
437+
assert.True(t, allowed, "token should refill for fractional rate after time passes")
438+
}
439+
413440
func generateAddressList(count int) []string {
414441
addrs := make([]string, count)
415442
for i := 0; i < count; i++ {

0 commit comments

Comments
 (0)