蛋蛋星球-客户端
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

1 месяц назад
1 месяц назад
1 месяц назад
1 месяц назад
1 месяц назад
2 недель назад
1 месяц назад
1 месяц назад
2 недель назад
1 месяц назад
2 недель назад
1 месяц назад
1 месяц назад
2 недель назад
1 месяц назад
1 месяц назад
1 месяц назад
2 недель назад
1 месяц назад
1 месяц назад
1 месяц назад
2 недель назад
1 месяц назад
1 месяц назад
1 месяц назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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 := c.ClientIP()
  17. // 读取token或者ip
  18. token := c.GetHeader("Authorization")
  19. // 判断是否已经超出限额次数
  20. method := c.Request.Method
  21. host := c.Request.Host
  22. uri := c.Request.URL.String()
  23. buf := make([]byte, 5120*50)
  24. num, _ := c.Request.Body.Read(buf)
  25. body := buf[:num]
  26. //body, _ := ioutil.ReadAll(c.Request.Body)
  27. // Write body back
  28. c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
  29. //queryValue := utils.SerializeStr(c.Request.URL.Query()) //不建议开启,失去限流的意义
  30. //TODO::分布式锁阻拦(保证原子性)
  31. requestIdPrefix := fmt.Sprintf(md.DealAppLimiterRequestIdPrefix, ip)
  32. cb, err := svc.HandleLimiterDistributedLock(ip, requestIdPrefix)
  33. if err != nil {
  34. e.OutErr(c, e.ERR, err.Error())
  35. return
  36. }
  37. if cb != nil {
  38. defer cb() // 释放锁
  39. }
  40. Md5 := utils.Md5(ip + token + method + host + uri + string(body))
  41. //Md5 := utils.Md5(ip + token + method + host + uri + string(body) + queryValue)
  42. //if cache.Exists(Md5) {
  43. // c.AbortWithStatusJSON(428, gin.H{
  44. // "code": 428,
  45. // "msg": "don't repeat the request",
  46. // "data": struct{}{},
  47. // })
  48. // return
  49. //}
  50. // 2s后没返回自动释放
  51. go cache.SetEx(Md5, "0", ttl)
  52. key := "LIMITER_APP_EGG_" + ip
  53. reqs, _ := cache.GetInt(key)
  54. if reqs >= limit {
  55. c.AbortWithStatusJSON(429, gin.H{
  56. "code": 429,
  57. "msg": "too many requests",
  58. "data": struct{}{},
  59. })
  60. return
  61. }
  62. if reqs > 0 {
  63. //go cache.Incr(key)
  64. go cache.SetEx(key, reqs+1, ttl)
  65. } else {
  66. go cache.SetEx(key, 1, ttl)
  67. }
  68. c.Next()
  69. go cache.Del(Md5)
  70. }