['count' => 1000, 'window' => 3600], 'POST' => ['count' => 100, 'window' => 3600], 'PUT' => ['count' => 100, 'window' => 3600], 'PATCH' => ['count' => 100, 'window' => 3600], 'DELETE' => ['count' => 50, 'window' => 3600], ]; /** * Check if request is within rate limits * * @param WP_REST_Request $request * @param int|null $limit Optional custom limit (overrides defaults) * @param int|null $window Optional custom window in seconds (overrides defaults) * @return bool True if within limits, false if exceeded */ public function checkLimit(WP_REST_Request $request, ?int $limit = null, ?int $window = null): bool { $method = $request->get_method(); $default = $this->defaults[$method] ?? $this->defaults['GET']; $limit = $limit ?? $default['count']; $window = $window ?? $default['window']; $key = $this->getCacheKey($request, $window); $current = (int) wp_cache_get($key, $this->cacheGroup); if ($current >= $limit) { return false; } // Increment or initialize if ($current === 0) { wp_cache_set($key, 1, $this->cacheGroup, $window); } else { wp_cache_incr($key, 1, $this->cacheGroup); } return true; } /** * Get remaining requests for current window */ public function getRemaining(WP_REST_Request $request, ?int $limit = null, ?int $window = null): int { $method = $request->get_method(); $default = $this->defaults[$method] ?? $this->defaults['GET']; $limit = $limit ?? $default['count']; $window = $window ?? $default['window']; $key = $this->getCacheKey($request, $window); $current = (int) wp_cache_get($key, $this->cacheGroup); return max(0, $limit - $current); } /** * Reset rate limit for a request pattern */ public function reset(WP_REST_Request $request, ?int $window = null): void { $method = $request->get_method(); $default = $this->defaults[$method] ?? $this->defaults['GET']; $window = $window ?? $default['window']; $key = $this->getCacheKey($request, $window); wp_cache_delete($key, $this->cacheGroup); } protected function getCacheKey(WP_REST_Request $request, int $window): string { $ip = $request->get_header('X-Forwarded-For') ?: ($_SERVER['REMOTE_ADDR'] ?? 'unknown'); $userId = get_current_user_id(); $method = $request->get_method(); $route = $request->get_route(); // Include window in key so different windows don't collide return "rate:{$ip}:{$userId}:{$method}:{$route}:{$window}"; } }