Rate Limit Middleware¶
Limits the number of requests per client within a time window.
Usage¶
Basic Usage¶
With Cleanup (Recommended)¶
rl := middleware.NewRateLimiter(middleware.RateLimitConfig{
Requests: 100,
Window: time.Minute,
})
defer rl.Stop() // Clean up goroutine on shutdown
app.Use(rl.Middleware())
Configuration¶
| Option | Type | Description |
|---|---|---|
Requests | int | Max requests per window |
Window | time.Duration | Time window |
KeyFunc | func(*Ctx) string | Function to identify clients |
Skip | func(*Ctx) bool | Skip rate limiting for certain requests |
OnLimitReached | func(*Ctx) error | Custom response when limit exceeded |
Response Headers¶
The middleware sets these headers on every response:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed |
X-RateLimit-Remaining | Requests remaining in window |
X-RateLimit-Reset | Unix timestamp when window resets |
Retry-After | Seconds until retry (when limited) |
Default Behavior¶
By default, clients are identified by IP address using c.ClientIP().
Examples¶
Basic Rate Limiting¶
// 100 requests per minute per IP
app.Use(middleware.RateLimit(middleware.RateLimitConfig{
Requests: 100,
Window: time.Minute,
}))
Strict Rate Limiting¶
// 10 requests per second per IP
app.Use(middleware.RateLimit(middleware.RateLimitConfig{
Requests: 10,
Window: time.Second,
}))
Custom Key Function¶
// Rate limit by API key
app.Use(middleware.RateLimit(middleware.RateLimitConfig{
Requests: 1000,
Window: time.Hour,
KeyFunc: func(c *marten.Ctx) string {
return c.Request.Header.Get("X-API-Key")
},
}))
Skip Certain Requests¶
rl := middleware.NewRateLimiter(middleware.RateLimitConfig{
Requests: 100,
Window: time.Minute,
Skip: func(c *marten.Ctx) bool {
// Skip health checks
return c.Path() == "/health"
},
})
defer rl.Stop()
app.Use(rl.Middleware())
Rate Limit by User¶
// Rate limit authenticated users
api := app.Group("/api")
api.Use(authMiddleware)
api.Use(middleware.RateLimit(middleware.RateLimitConfig{
Requests: 100,
Window: time.Minute,
KeyFunc: func(c *marten.Ctx) string {
return c.GetString("user_id")
},
}))
Custom Rate Limit Response¶
rl := middleware.NewRateLimiter(middleware.RateLimitConfig{
Requests: 100,
Window: time.Minute,
OnLimitReached: func(c *marten.Ctx) error {
return c.JSON(429, marten.M{
"error": "rate_limit_exceeded",
"message": "Please slow down and try again later",
"retry_after": c.Writer.Header().Get("Retry-After"),
})
},
})
defer rl.Stop()
app.Use(rl.Middleware())
Response¶
When rate limit is exceeded:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1704067200
Retry-After: 45
{"error": "rate limit exceeded"}
Different Limits for Different Routes¶
// Strict limit for auth endpoints
authRL := middleware.NewRateLimiter(middleware.RateLimitConfig{
Requests: 5,
Window: time.Minute,
})
defer authRL.Stop()
auth := app.Group("/auth")
auth.Use(authRL.Middleware())
auth.POST("/login", login)
// Relaxed limit for API
apiRL := middleware.NewRateLimiter(middleware.RateLimitConfig{
Requests: 100,
Window: time.Minute,
})
defer apiRL.Stop()
api := app.Group("/api")
api.Use(apiRL.Middleware())
api.GET("/users", listUsers)
Best Practices¶
- Use
NewRateLimiterwithStop()for proper cleanup - Set appropriate limits - Too strict frustrates users, too relaxed allows abuse
- Use different limits for different endpoints
- Consider authenticated vs anonymous users
- Monitor rate limit hits to adjust limits