RestfulRateLimitManager.php in RESTful 7
File
plugins/rate_limit/RestfulRateLimitManager.php
View source
<?php
class RestfulRateLimitManager extends \RestfulPluginBase {
const UNLIMITED_RATE_LIMIT = -1;
protected $account;
protected $resource;
public function setAccount($account) {
$this->account = $account;
}
public function getAccount() {
return $this->account;
}
public function setPluginInfo($pluginInfo) {
$this->pluginInfo = $pluginInfo;
}
public function __construct($resource, array $plugin, $account = NULL) {
parent::__construct($plugin);
$this->resource = $resource;
$this
->setPluginInfo($plugin);
$this->account = $account ? $account : drupal_anonymous_user();
}
public function checkRateLimit($request) {
$now = new \DateTime();
$now
->setTimestamp(REQUEST_TIME);
foreach ($this
->getPlugin() as $event_name => $info) {
$rate_limit_plugin = restful_get_rate_limit_plugin($info['event']);
$rate_limit_class = ctools_plugin_get_class($rate_limit_plugin, 'class');
$handler = new $rate_limit_class($info, $this->resource);
$limit = $handler
->getLimit($this->account);
$period = $handler
->getPeriod();
if ($limit == static::UNLIMITED_RATE_LIMIT) {
continue;
}
if (!$handler
->isRequestedEvent($request)) {
continue;
}
if (!($rate_limit_entity = $handler
->loadRateLimitEntity($this->account))) {
$rate_limit_entity = entity_create('rate_limit', array(
'timestamp' => REQUEST_TIME,
'expiration' => $now
->add($period)
->format('U'),
'hits' => 0,
'event' => $event_name,
'identifier' => $handler
->generateIdentifier($this->account),
));
}
$new_period = new \DateTime();
$new_period
->setTimestamp($rate_limit_entity->expiration);
if ($rate_limit_entity
->isExpired()) {
$rate_limit_entity->timestamp = REQUEST_TIME;
$rate_limit_entity->expiration = $now
->add($period)
->format('U');
$rate_limit_entity->hits = 0;
if ($limit == 0) {
$exception = new \RestfulFloodException('Rate limit reached');
$exception
->setHeader('Retry-After', $new_period
->format(\DateTime::RFC822));
throw $exception;
}
}
else {
if ($rate_limit_entity->hits >= $limit) {
$exception = new \RestfulFloodException('Rate limit reached');
$exception
->setHeader('Retry-After', $new_period
->format(\DateTime::RFC822));
throw $exception;
}
}
$rate_limit_entity
->hit();
$remaining = $limit == static::UNLIMITED_RATE_LIMIT ? 'unlimited' : $limit - ($rate_limit_entity->hits + 1);
drupal_add_http_header('X-Rate-Limit-Limit', $limit, TRUE);
drupal_add_http_header('X-Rate-Limit-Remaining', $remaining, TRUE);
$time_remaining = $rate_limit_entity->expiration - REQUEST_TIME;
drupal_add_http_header('X-Rate-Limit-Reset', $time_remaining, TRUE);
}
}
public static function deleteExpired() {
$query = new \EntityFieldQuery();
$results = $query
->entityCondition('entity_type', 'rate_limit')
->propertyCondition('expiration', REQUEST_TIME, '>')
->execute();
if (!empty($results['rate_limit'])) {
$rlids = array_keys($results['rate_limit']);
entity_delete_multiple('rate_limit', $rlids);
}
}
}