1. <?php
  2. class HTTPCache {
  3. private $cache = [];
  4. private $rateLimit = 10; // Requests per second
  5. private $lastRequestTime = 0;
  6. private $cacheDuration = 60; //Cache duration in seconds
  7. private $proxy = null; //Optional proxy object
  8. public function __construct($proxy = null) {
  9. $this->proxy = $proxy;
  10. }
  11. /**
  12. * Makes an HTTP request, caching the result.
  13. *
  14. * @param string $url The URL to request.
  15. * @param callable $callback A callback function to execute with the response data.
  16. * @return mixed The result of the callback function.
  17. * @throws Exception If rate limit is exceeded.
  18. */
  19. public function get($url, callable $callback) {
  20. //Check if the request is already in the cache and within the cache duration
  21. if ($this->isCached($url)) {
  22. return $this->cache[$url];
  23. }
  24. // Apply rate limiting
  25. $currentTime = time();
  26. if ($currentTime - $this->lastRequestTime < 1 / $this->rateLimit) {
  27. throw new Exception("Rate limit exceeded.");
  28. }
  29. $this->lastRequestTime = $currentTime;
  30. try {
  31. $response = $this->makeRequest($url);
  32. if ($response) {
  33. $this->cache[$url] = $response;
  34. $this->cacheExpiration($url, $this->cacheDuration);
  35. return $callback($response);
  36. } else {
  37. return null; //Or handle the error as needed. Can return an empty array or similar.
  38. }
  39. } catch (Exception $e) {
  40. //Handle exceptions (e.g., network errors, HTTP errors)
  41. error_log("HTTP Request Error: " . $url . " - " . $e->getMessage());
  42. throw $e; // Re-throw the exception to be handled by the caller.
  43. }
  44. }
  45. /**
  46. * Checks if a URL is in the cache and if it's still valid.
  47. *
  48. * @param string $url The URL to check.
  49. * @return bool True if the URL is in the cache and not expired, false otherwise.
  50. */
  51. private function isCached(string $url): bool {
  52. if (!isset($this->cache[$url])) {
  53. return false;
  54. }
  55. $cacheEntry = $this->cache[$url];
  56. if ($cacheEntry['expiry'] > time()) {
  57. return true;
  58. } else {
  59. $this->deleteCacheEntry($url);
  60. return false;
  61. }
  62. }
  63. /**
  64. * Makes an HTTP request. Uses cURL.
  65. *
  66. * @param string $url The URL to request.
  67. * @return string|null The response body, or null on error.
  68. * @throws Exception If the request fails.
  69. */
  70. private function makeRequest(string $url): ?string {
  71. $ch = $this->proxy ? curl_init($url) : curl_init($url);
  72. if ($ch === false) {
  73. throw new Exception("cURL initialization failed.");
  74. }
  75. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  76. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //Follow redirects
  77. curl_setopt($ch, CURLOPT_TIMEOUT, 10); // Set a timeout
  78. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Disable SSL verification (for testing only!)
  79. $response = curl_exec($ch);
  80. if ($response === false) {
  81. $error = curl_error($ch);
  82. throw new Exception("cURL error: " . $error);
  83. }
  84. curl_close($ch);
  85. return $response;
  86. }
  87. /**
  88. * Expires a cache entry.
  89. *
  90. * @param string $url The URL of the cached entry.
  91. * @param int $duration The cache duration in seconds.
  92. */
  93. private function cacheExpiration(string $url, int $duration): void {
  94. $this->cache[$url]['expiry'] = time() + $duration;
  95. }
  96. /**
  97. * Deletes a cache entry.
  98. *
  99. * @param string $url The URL of the entry to delete.
  100. */
  101. private function

Add your comment