feat: add global and burst rate limiters
Three layers of rate limiting, all disabled by default, opt-in via config: 1. Per-IP (existing): 30 req/min per IP 2. Global: server-wide limit across all IPs - Lock-free atomic counter for minimal overhead - Returns 503 when exceeded - Prevents pool exhaustion from distributed attacks 3. Burst: per-IP burst + sustained windows - Blocks rapid-fire abuse within seconds - Returns 429 with X-RateLimit-Reason header - Example: 5 req/5s burst, 60 req/min sustained Config: [global_rate_limit] requests = 0 # disabled by default window = "1m" [burst_rate_limit] burst = 0 # disabled by default burst_window = "5s" sustained = 0 sustained_window = "1m" Env overrides: GLOBAL_RATE_LIMIT_REQUESTS, GLOBAL_RATE_LIMIT_WINDOW, BURST_RATE_LIMIT_BURST, BURST_RATE_LIMIT_BURST_WINDOW, BURST_RATE_LIMIT_SUSTAINED, BURST_RATE_LIMIT_SUSTAINED_WINDOW Full test coverage: concurrent lock-free test, window expiry, disabled states, IP isolation, burst vs sustained distinction.
This commit is contained in:
parent
91ab76758c
commit
13040268d6
7 changed files with 657 additions and 18 deletions
|
|
@ -73,7 +73,7 @@ func main() {
|
|||
var subFS fs.FS = staticFS
|
||||
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(subFS))))
|
||||
|
||||
// Apply middleware: rate limiter → CORS → handler.
|
||||
// Apply middleware: global rate limit → burst rate limit → per-IP rate limit → CORS → handler.
|
||||
var handler http.Handler = mux
|
||||
handler = middleware.CORS(middleware.CORSConfig{
|
||||
AllowedOrigins: cfg.CORS.AllowedOrigins,
|
||||
|
|
@ -87,6 +87,16 @@ func main() {
|
|||
Window: cfg.RateLimitWindow(),
|
||||
CleanupInterval: cfg.RateLimitCleanupInterval(),
|
||||
}, logger)(handler)
|
||||
handler = middleware.GlobalRateLimit(middleware.GlobalRateLimitConfig{
|
||||
Requests: cfg.GlobalRateLimit.Requests,
|
||||
Window: cfg.GlobalRateLimitWindow(),
|
||||
}, logger)(handler)
|
||||
handler = middleware.BurstRateLimit(middleware.BurstRateLimitConfig{
|
||||
Burst: cfg.BurstRateLimit.Burst,
|
||||
BurstWindow: cfg.BurstWindow(),
|
||||
Sustained: cfg.BurstRateLimit.Sustained,
|
||||
SustainedWindow: cfg.SustainedWindow(),
|
||||
}, logger)(handler)
|
||||
|
||||
addr := fmt.Sprintf(":%d", cfg.Server.Port)
|
||||
logger.Info("searxng-go starting",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue