package mw import ( "bytes" "io/ioutil" "github.com/gin-gonic/gin" "applet/app/utils" "applet/app/utils/cache" ) // Limiter 限流器 func Limiter(c *gin.Context) { limit := 100 // 限流次数 ttl := 1 // 限流过期时间 ip := c.ClientIP() // 读取token或者ip token := c.GetHeader("Authorization") // 判断是否已经超出限额次数 method := c.Request.Method host := c.Request.Host uri := c.Request.URL.String() buf := make([]byte, 2048) num, _ := c.Request.Body.Read(buf) body := buf[:num] // Write body back c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body)) Md5 := utils.Md5(ip + token + method + host + uri + string(body)) if cache.Exists(Md5) { c.AbortWithStatusJSON(429, gin.H{ "code": 429, "msg": "don't repeat the request", "data": struct{}{}, }) return } // 2s后没返回自动释放 go cache.SetEx(Md5, "0", ttl) key := "LIMITER_" + ip reqs, _ := cache.GetInt(key) if reqs >= limit { c.AbortWithStatusJSON(429, gin.H{ "code": 429, "msg": "too many requests", "data": struct{}{}, }) return } if reqs > 0 { go cache.Incr(key) } else { go cache.SetEx(key, 1, ttl) } c.Next() go cache.Del(Md5) }