Documentation
¶
Overview ¶
Package slidingwindow provides a sliding window rate limiter middleware. Unlike fixed-window limiters, sliding window accurately tracks request rates across window boundaries, preventing burst spikes at window edges.
The algorithm uses a logarithmic counter approach: - Each request increments a counter with a timestamp - Old requests are expired based on the window size - The rate is calculated as requests-per-second over the window
Features: - Per-IP, per-key, or global rate limiting - Burst allowance for short traffic spikes - Retry-After header support - Custom key extraction (by IP, header, route, etc.) - Clean headers: X-RateLimit-*, Retry-After
Index ¶
- Variables
- func Allow(store kv.Store, key string, rate, burst int, windowSize time.Duration) (allowed bool, remaining int, retryAfter time.Duration, err error)
- func ByComposite(fns ...func(fh.Ctx) string) func(fh.Ctx) string
- func ByHeader(name string) func(fh.Ctx) string
- func ByIP(ctx fh.Ctx) string
- func ByRoute(ctx fh.Ctx) string
- func New(config ...Config) fh.HandlerFunc
- type Config
- type Limiter
Constants ¶
This section is empty.
Variables ¶
var DefaultConfig = Config{ Rate: 100, Burst: 100, Window: time.Second, MaxKeys: 65536, CleanupInterval: time.Minute, Message: "Rate limit exceeded", StatusCode: 429, }
DefaultConfig returns the default configuration.
Functions ¶
func Allow ¶
func Allow(store kv.Store, key string, rate, burst int, windowSize time.Duration) (allowed bool, remaining int, retryAfter time.Duration, err error)
allowViaStore implements Store.Allow on top of any kv.Store, shared by MemoryStore and FileStore. It reproduces the exact admission algorithm this package has always used (expire timestamps outside the window, compute remaining against rate, allow bursts up to rate+burst, otherwise reject with a retry-after derived from the oldest in-window timestamp); only the representation changes, from an in-memory compacting ring buffer (an optimization to avoid reallocating the timestamp slice on every request) to a plain trimmed slice that round-trips through JSON on every Mutate call, since kv.Store already reallocates on every write and the ring buffer's head/count bookkeeping has nothing left to optimize once that's true.
func ByComposite ¶
ByComposite combines multiple key functions.
func New ¶
func New(config ...Config) fh.HandlerFunc
New creates a sliding window rate limiter middleware.
Types ¶
type Config ¶
type Config struct {
// Rate is the maximum requests per window. Default: 100.
Rate int
// Burst is the maximum burst size above the rate. Default: same as Rate.
Burst int
// Window is the sliding window duration. Default: 1 second.
Window time.Duration
// KeyFunc extracts the rate limit key from the request.
// Default: client IP address.
KeyFunc func(ctx fh.Ctx) string
// MaxKeys is the maximum number of tracked keys. Default: 65536.
MaxKeys int
// CleanupInterval is how often to clean expired keys. Default: 1 minute.
CleanupInterval time.Duration
// Message is the error message for rate-limited requests.
Message string
// StatusCode is the HTTP status for rate-limited requests. Default: 429.
StatusCode int
// Next is an optional skip function.
Next func(ctx fh.Ctx) bool
// OnLimitReached is called when a request is rate-limited.
OnLimitReached func(ctx fh.Ctx, key string, remaining int)
// Store holds per-key sliding window state. Defaults to a new kv.MemoryStore.
// Pass any kv.Store implementation, such as kv.NewFileStore, when creating
// the middleware.
Store kv.Store
}
Config holds configuration for the sliding window rate limiter.
type Limiter ¶
type Limiter struct {
// contains filtered or unexported fields
}
func NewLimiter ¶
NewLimiter creates a new sliding window rate limiter.
func (*Limiter) Allow ¶
Allow checks if a request with the given key is allowed. Returns (allowed, remaining, retryAfter).