<?php
/**
* API Endpoint Rate Limiter for Scheduled Runs
*
* Reads configuration from a file to define limits and enforces them.
*/
class RateLimiter {
private $config;
private $request_counts = []; // Stores request counts per endpoint and user/identifier
public function __construct(string $config_file) {
$this->config = $this->loadConfig($config_file);
}
/**
* Loads the configuration from the specified file.
* @param string $config_file Path to the configuration file.
* @return array|null An associative array containing the configuration data.
*/
private function loadConfig(string $config_file): ?array {
if (file_exists($config_file)) {
$config = json_decode(file_get_contents($config_file), true);
if (json_last_error() !== JSON_ERROR_NONE) {
error_log("Error decoding config file: " . json_last_error_msg());
return null;
}
return $config;
} else {
error_log("Config file not found: " . $config_file);
return null;
}
}
/**
* Checks if an API endpoint request is allowed based on the configuration.
* @param string $endpoint The API endpoint being called.
* @param string $user_identifier A unique identifier for the user/system making the request.
* @return bool True if the request is allowed, false otherwise.
*/
public function isAllowed(string $endpoint, string $user_identifier): bool {
if (!isset($this->config[$endpoint])) {
// Endpoint not configured, allow unlimited requests.
return true;
}
$limit = $this->config[$endpoint]['limit'];
$window = $this->config[$endpoint]['window'];
if (empty($this->request_counts[$user_identifier][$endpoint])) {
$this->request_counts[$user_identifier][$endpoint] = [
'count' => 0,
'last_reset' => time()
];
}
$current_count = $this->request_counts[$user_identifier][$endpoint]['count'];
if (time() - $this->request_counts[$user_identifier][$endpoint]['last_reset'] > $window) {
$current_count = 0; // Reset count at the beginning of the window
}
if ($current_count < $limit) {
$this->request_counts[$user_identifier][$endpoint]['count']++;
$this->request_counts[$user_identifier][$endpoint]['last_reset'] = time();
return true;
} else {
return false; // Rate limit exceeded
}
}
/**
* Resets the request count for a user and endpoint.
* @param string $user_identifier The identifier of the user.
* @param string $endpoint The API endpoint.
*/
public function resetCount(string $user_identifier, string $endpoint): void {
if (isset($this->request_counts[$user_identifier][$endpoint])) {
$this->request_counts[$user_identifier][$endpoint]['count'] = 0;
$this->request_counts[$user_identifier][$endpoint]['last_reset'] = time();
}
}
}
// Example Usage (within your API endpoint handler)
/*
$rateLimiter = new RateLimiter('config.json');
if ($rateLimiter->isAllowed('scheduled_task', 'user123')) {
// Process the API request
echo "Request allowed!";
} else {
// Rate limit exceeded
header('HTTP/1.1 429 Too Many Requests');
echo 'Rate limit exceeded. Please try again later.';
exit;
}
*/
?>
Add your comment