Skip to content

Instantly share code, notes, and snippets.

@saaiful
Created January 29, 2025 21:13
Show Gist options
  • Save saaiful/ff61e5b782e54e78f27cc932b6172566 to your computer and use it in GitHub Desktop.
Save saaiful/ff61e5b782e54e78f27cc932b6172566 to your computer and use it in GitHub Desktop.
Laravel Route Cache
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Facades\Cache;
class CacheResponse
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param int|null $cacheSeconds
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handle(Request $request, Closure $next, $cacheDuration = 0): Response
{
// Bypass Cache for authenticated users and non GET requests
if (auth()->check() || !$request->isMethod('GET')) {
return $next($request);
}
$server_cache = false;
if ($cacheDuration != 0) {
$params = explode('|', $cacheDuration);
$cacheDuration = $params[0];
$server_cache = isset($params[1]) ? true : false;
}
if ($cacheDuration <= 0) {
return $next($request);
}
// Generate unique cache key
$url_sha1 = sha1($request->url());
$cacheKey = "route_cache:{$url_sha1}";
// Return cached response if available
$cached = Cache::get($cacheKey);
if ($cached) {
$response = response($cached['content']);
$response->setContent(preg_replace('/##CSRF##/', csrf_token(), $cached['content']));
foreach ($cached['headers'] as $header => $values) {
$response->headers->set($header, $values);
}
/*
* If you want to cache the response on the server side
* you can use the following code to set the cache control
* header to the remaining time left for the cache to expire
* and return the response.
* Important: This will cache the response on the server side, so use it with caution.
*/
if ($server_cache === true) {
$timeLeft = $cached['time']->diffInSeconds(now());
$response->headers->set('Cache-Control', "public, max-age={$timeLeft}");
$response->headers->set('ETag', $url_sha1);
$response->headers->set('Expires', now()->addSeconds($timeLeft)->toRfc7231String());
}
return $response;
}
// Process request and cache response
$response = $next($request);
if ($response->isSuccessful()) {
$headers = collect($response->headers->all())
->except(['Set-Cookie', 'Cache-Control'])
->toArray();
$content = $response->getContent();
// Inject CSRF token to cached content
$content = preg_replace('/data-csrf=".*?"/', 'data-csrf="##CSRF##"', $content);
$content = preg_replace('/name="csrf-token" content=".*?"/', 'name="csrf-token" content="##CSRF##"', $content);
Cache::put($cacheKey, [
'content' => $content,
'headers' => $headers,
'time' => now()
], now()->addSeconds($cacheDuration));
}
return $response;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment