init: web_hgdjc_server
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package apilimitHandler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type counter struct {
|
||||
Count int
|
||||
WindowStart time.Time
|
||||
}
|
||||
|
||||
type RouteHourlyLimiter struct {
|
||||
mu sync.Mutex
|
||||
limit int
|
||||
window time.Duration
|
||||
counters map[string]*counter
|
||||
}
|
||||
|
||||
func NewRouteHourlyLimiter(limit int) *RouteHourlyLimiter {
|
||||
l := &RouteHourlyLimiter{
|
||||
limit: limit,
|
||||
window: time.Hour,
|
||||
counters: make(map[string]*counter),
|
||||
}
|
||||
go l.cleaner()
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *RouteHourlyLimiter) Middleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 用 FullPath 做“接口维度”,例如 /api/user/:id
|
||||
route := c.FullPath()
|
||||
if route == "" {
|
||||
// 路由未匹配时兜底
|
||||
route = c.Request.URL.Path
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
||||
item, ok := l.counters[route]
|
||||
if !ok || now.Sub(item.WindowStart) >= l.window {
|
||||
l.counters[route] = &counter{
|
||||
Count: 1,
|
||||
WindowStart: now,
|
||||
}
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
if item.Count >= l.limit {
|
||||
c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{
|
||||
"code": http.StatusTooManyRequests,
|
||||
"message": "rate limit exceeded: max 100 requests per route per hour",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
item.Count++
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// 定时清理过期窗口,避免 map 无限增长
|
||||
func (l *RouteHourlyLimiter) cleaner() {
|
||||
ticker := time.NewTicker(10 * time.Minute)
|
||||
defer ticker.Stop()
|
||||
|
||||
for now := range ticker.C {
|
||||
l.mu.Lock()
|
||||
for k, v := range l.counters {
|
||||
if now.Sub(v.WindowStart) >= l.window {
|
||||
delete(l.counters, k)
|
||||
}
|
||||
}
|
||||
l.mu.Unlock()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user