You've already forked Atomcms-edit
95 lines
2.6 KiB
PHP
Executable File
95 lines
2.6 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use Closure;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class ApiResponseCache
|
|
{
|
|
private const int DEFAULT_TTL = 60;
|
|
|
|
public function handle(Request $request, Closure $next): Response
|
|
{
|
|
if (! $this->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,
|
|
};
|
|
}
|
|
}
|