shouldCache($request)) { return $next($request); } $cacheKey = $this->generateCacheKey($request); if (Cache::has($cacheKey)) { $cached = Cache::get($cacheKey); if (is_array($cached) && isset($cached['data'], $cached['status'])) { return response()->json($cached['data'], $cached['status'], $cached['headers'] ?? []); } } $response = $next($request); if ($response->isSuccessful()) { $ttl = $this->getTtlFromRoute($request); $data = json_decode((string) $response->getContent(), true); if (is_array($data)) { Cache::put($cacheKey, [ 'data' => $data, 'status' => $response->getStatusCode(), ], $ttl); } } return $response; } private function shouldCache(Request $request): bool { if (! in_array($request->method(), ['GET', 'HEAD'])) { return false; } if ($request->bearerToken()) { return false; } $cacheableRoutes = [ '/api/online-users', '/api/online-count', '/api/radio/current-dj', '/api/radio/config', '/api/radio/now-playing', '/api/radio/listeners', '/api/radio/shouts', '/api/settings/radio', '/api/radio/points/leaderboard', '/api/radio/points/stats', ]; return array_any($cacheableRoutes, fn ($route) => str_starts_with($request->path(), ltrim((string) $route, '/'))); } private function generateCacheKey(Request $request): string { return 'api_cache_' . md5($request->path() . ($request->getQueryString() ?? '')); } private function getTtlFromRoute(Request $request): int { $path = $request->path(); return match (true) { str_contains($path, 'online-count') => 30, str_contains($path, 'now-playing') => 15, str_contains($path, 'current-dj') => 30, str_contains($path, 'listeners') => 30, str_contains($path, 'leaderboard') => 60, str_contains($path, 'shouts') => 30, default => self::DEFAULT_TTL, }; } }