diff --git a/config/rapidez.php b/config/rapidez.php index 489c61dd6..327553035 100644 --- a/config/rapidez.php +++ b/config/rapidez.php @@ -55,6 +55,13 @@ // below will not be used anymore when disabled. 'routes' => true, + 'fallback_routes' => [ + // How long (in seconds) it should cache which controller handles which route. + // null means cache forever, 0 means never cache. customisation is possible using a closure. + // This does not cache the response, it caches the controller used for that page. + 'cache_duration' => 3600, + ], + // Link store codes to theme folders // The structure is `'store_code' => 'folder_path'` 'themes' => [ diff --git a/src/Http/Controllers/FallbackController.php b/src/Http/Controllers/FallbackController.php index a54cc8cae..b16e085b5 100644 --- a/src/Http/Controllers/FallbackController.php +++ b/src/Http/Controllers/FallbackController.php @@ -2,32 +2,58 @@ namespace Rapidez\Core\Http\Controllers; +use Exception; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\RecordsNotFoundException; +use Illuminate\Http\Request; use Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Cache; use Rapidez\Core\Facades\Rapidez; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Exception\RouteNotFoundException; class FallbackController { - public function __invoke() + public function __invoke(Request $request) { - foreach (Rapidez::getAllFallbackRoutes() as $route) { - try { - $response = App::call($route['action']['uses']); + $cacheKey = 'fallbackroute-' . md5($request->url()); + $route = Cache::get($cacheKey); + if($route && $response = $this->tryRoute($route)) { + return $response; + } - // Null response is equal to no response or 404. - if ($response === null) { - abort(404); - } + foreach (Rapidez::getAllFallbackRoutes() as $route) { + if(!($response = $this->tryRoute($route))) { + continue; + } - return $response; - } catch (RouteNotFoundException|NotFoundHttpException|BackedEnumCaseNotFoundException|ModelNotFoundException|RecordsNotFoundException $e) { + try { + Cache::put($cacheKey, $route, value(config('rapidez.fallback_routes.cache_duration', 3600), $request, $response, $route)); + } catch (Exception $e) { + // We can't cache it, no worries. + // Ususally a sign it's a direct callback or caching hasn't been configured properly. } + + return $response; } abort(404); } + + protected function tryRoute($route) + { + try { + $response = App::call($route['action']['uses']); + + // Null response is equal to no response or 404. + if ($response === null) { + abort(404); + } + + return $response; + } catch (RouteNotFoundException|NotFoundHttpException|BackedEnumCaseNotFoundException|ModelNotFoundException|RecordsNotFoundException $e) { + return null; + } + } }