From f8e40be3d7b6a8cd255fad35e8e6663c6bd18a07 Mon Sep 17 00:00:00 2001 From: Manolis Date: Sat, 3 Sep 2016 14:37:41 +0300 Subject: [PATCH] Ability to call the rate limiter many times in the same php code with different limits --- ratelimiter.php | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/ratelimiter.php b/ratelimiter.php index 24bb875..996d1e5 100644 --- a/ratelimiter.php +++ b/ratelimiter.php @@ -27,10 +27,18 @@ class RateExceededException extends Exception {} class RateLimiter { - private $prefix, $memcache; + private $prefix, $memcache , $keysvisited; + // how long should we keep memcache entries + public $maxMinutes=10; + public function __construct(Memcache $memcache, $ip, $prefix = "rate") { $this->memcache = $memcache; + if (!$memcache) { + echo "Problem connecting to memcache server"; + exit; + } $this->prefix = $prefix . $ip; + $keysvisited=array(); } public function limitRequestsInMinutes($allowedRequests, $minutes) { @@ -38,15 +46,28 @@ public function limitRequestsInMinutes($allowedRequests, $minutes) { foreach ($this->getKeys($minutes) as $key) { $requestsInCurrentMinute = $this->memcache->get($key); + + // if the key is read for a second or third tim in the same + // php execution, we remove the previous additions so that the + // last call reports correct numbers + if ($this->keysvisited[$key]) { + $requestsInCurrentMinute-=$this->keysvisited[$key]; + } if (false !== $requestsInCurrentMinute) $requests += $requestsInCurrentMinute; } - if (false === $requestsInCurrentMinute) { - $this->memcache->set($key, 1, 0, $minutes * 60 + 1); + if (! $this->keysvisited[$key] ) { + if (false === $requestsInCurrentMinute) { + $this->memcache->set($key, 1, 0, $this->maxMinutes * 60 + 1); + } else { + $this->memcache->increment($key, 1); + } + $this->keysvisited[$key]=1; } else { - $this->memcache->increment($key, 1); + $this->keysvisited[$key]++; } + echo " You already have $requests requests in $minutes min
"; if ($requests > $allowedRequests) throw new RateExceededException; }