servlimit.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. package servlimit
  2. import (
  3. "log"
  4. "net/http"
  5. "time"
  6. "github.com/vladimirok5959/golang-utils/utils/http/helpers"
  7. )
  8. var mRequests = &Requests{
  9. counter: map[string]int{},
  10. lastTime: map[string]int64{},
  11. cleanTime: time.Now().UTC().Unix(),
  12. }
  13. func ReqPerSecond(handler http.Handler, requests int) http.Handler {
  14. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  15. if requests > 0 {
  16. // Cleanup every hour
  17. if (time.Now().UTC().Unix() - mRequests.cleanTime) > 3600 {
  18. mRequests.Cleanup()
  19. }
  20. ip := helpers.ClientIP(r)
  21. reqs := mRequests.Count(ip)
  22. ltime := mRequests.Time(ip)
  23. // Inc counter
  24. reqs = reqs + 1
  25. mRequests.SetCount(ip, reqs)
  26. // Reset counter
  27. if (time.Now().UTC().Unix() - ltime) >= 1 {
  28. reqs = 0
  29. mRequests.SetCount(ip, reqs)
  30. }
  31. // Restrict access
  32. if reqs >= requests {
  33. w.Header().Set("Retry-After", "1")
  34. w.WriteHeader(429)
  35. if _, err := w.Write([]byte("Too Many Requests\n")); err != nil {
  36. log.Printf("%s\n", err.Error())
  37. }
  38. return
  39. }
  40. mRequests.SetTime(ip, time.Now().UTC().Unix())
  41. }
  42. handler.ServeHTTP(w, r)
  43. })
  44. }