package middleware import ( "net/http" "sync" "github.com/gin-gonic/gin" "golang.org/x/time/rate" ) type IPRateLimiter struct { ips map[string]*rate.Limiter mu *sync.RWMutex r rate.Limit b int } func NewIPRateLimiter(r rate.Limit, b int) *IPRateLimiter { return &IPRateLimiter{ ips: make(map[string]*rate.Limiter), mu: &sync.RWMutex{}, r: r, b: b, } } func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter { i.mu.Lock() defer i.mu.Unlock() limiter, exists := i.ips[ip] if !exists { limiter = rate.NewLimiter(i.r, i.b) i.ips[ip] = limiter } return limiter } func RateLimit(limiter *IPRateLimiter) gin.HandlerFunc { return func(c *gin.Context) { ip := c.ClientIP() if !limiter.GetLimiter(ip).Allow() { c.JSON(http.StatusTooManyRequests, gin.H{ "code": 429, "message": "too many requests", }) c.Abort() return } c.Next() } }