广告平台(站长下代理使用)
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

59 řádky
1.2 KiB

  1. package mw
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "github.com/gin-gonic/gin"
  6. "applet/app/utils"
  7. "applet/app/utils/cache"
  8. )
  9. // 限流器
  10. func Limiter(c *gin.Context) {
  11. limit := 100 // 限流次数
  12. ttl := 1 // 限流过期时间
  13. ip := c.ClientIP()
  14. // 读取token或者ip
  15. token := c.GetHeader("Authorization")
  16. // 判断是否已经超出限额次数
  17. method := c.Request.Method
  18. host := c.Request.Host
  19. uri := c.Request.URL.String()
  20. buf := make([]byte, 2048)
  21. num, _ := c.Request.Body.Read(buf)
  22. body := buf[:num]
  23. // Write body back
  24. c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
  25. Md5 := utils.Md5(ip + token + method + host + uri + string(body))
  26. if cache.Exists(Md5) {
  27. c.AbortWithStatusJSON(429, gin.H{
  28. "code": 429,
  29. "msg": "don't repeat the request",
  30. "data": struct{}{},
  31. })
  32. return
  33. }
  34. // 2s后没返回自动释放
  35. go cache.SetEx(Md5, "0", ttl)
  36. key := "LIMITER_" + ip
  37. reqs, _ := cache.GetInt(key)
  38. if reqs >= limit {
  39. c.AbortWithStatusJSON(429, gin.H{
  40. "code": 429,
  41. "msg": "too many requests",
  42. "data": struct{}{},
  43. })
  44. return
  45. }
  46. if reqs > 0 {
  47. go cache.Incr(key)
  48. } else {
  49. go cache.SetEx(key, 1, ttl)
  50. }
  51. c.Next()
  52. go cache.Del(Md5)
  53. }