蛋蛋星球-客户端
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

83 行
1.9 KiB

  1. package mw
  2. import (
  3. "applet/app/e"
  4. "applet/app/md"
  5. "applet/app/svc"
  6. "applet/app/utils"
  7. "applet/app/utils/cache"
  8. "bytes"
  9. "fmt"
  10. "github.com/gin-gonic/gin"
  11. "io/ioutil"
  12. )
  13. func Limiter(c *gin.Context) {
  14. limit := 500 // 限流次数
  15. ttl := 2 // 限流过期时间
  16. ip := utils.GetIP(c.Request)
  17. //if ip != "221.4.210.167" {
  18. // e.OutErr(c, e.ERR, "系统维护中~")
  19. // return
  20. //}
  21. // 读取token或者ip
  22. token := c.GetHeader("Authorization")
  23. // 判断是否已经超出限额次数
  24. method := c.Request.Method
  25. host := c.Request.Host
  26. uri := c.Request.URL.String()
  27. buf := make([]byte, 1024*1024)
  28. num, _ := c.Request.Body.Read(buf)
  29. body := buf[:num]
  30. //body, _ := ioutil.ReadAll(c.Request.Body)
  31. // Write body back
  32. c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
  33. //queryValue := utils.SerializeStr(c.Request.URL.Query()) //不建议开启,失去限流的意义
  34. //TODO::分布式锁阻拦(保证原子性)
  35. requestIdPrefix := fmt.Sprintf(md.DealAppLimiterRequestIdPrefix, ip)
  36. cb, err := svc.HandleLimiterDistributedLock(ip, requestIdPrefix)
  37. if err != nil {
  38. e.OutErr(c, e.ERR, err.Error())
  39. return
  40. }
  41. if cb != nil {
  42. defer cb() // 释放锁
  43. }
  44. Md5 := utils.Md5(ip + token + method + host + uri + string(body))
  45. //Md5 := utils.Md5(ip + token + method + host + uri + string(body) + queryValue)
  46. //if cache.Exists(Md5) {
  47. // c.AbortWithStatusJSON(428, gin.H{
  48. // "code": 428,
  49. // "msg": "don't repeat the request",
  50. // "data": struct{}{},
  51. // })
  52. // return
  53. //}
  54. // 2s后没返回自动释放
  55. go cache.SetEx(Md5, "0", ttl)
  56. key := "LIMITER_APP_EGG_" + ip
  57. reqs, _ := cache.GetInt(key)
  58. if reqs >= limit {
  59. c.AbortWithStatusJSON(429, gin.H{
  60. "code": 429,
  61. "msg": "too many requests",
  62. "data": struct{}{},
  63. })
  64. return
  65. }
  66. if reqs > 0 {
  67. //go cache.Incr(key)
  68. go cache.SetEx(key, reqs+1, ttl)
  69. } else {
  70. go cache.SetEx(key, 1, ttl)
  71. }
  72. c.Next()
  73. go cache.Del(Md5)
  74. }