diff --git a/bootstrap/app.php b/bootstrap/app.php index af4aed4..0e9e09d 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -2,6 +2,7 @@ use App\Http\Middleware\DomainMiddleware; use App\Http\Middleware\SetTimezone; +use Illuminate\Contracts\Filesystem\FileNotFoundException; use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; @@ -52,17 +53,33 @@ return Application::configure(basePath: dirname(__DIR__)) return false; }; - $exceptions->report(function (Throwable $e) use ($isStaleLivewireAsset) { + $isStaleCompiledView = function (Throwable $e): bool { + if (! $e instanceof FileNotFoundException) { + return false; + } + + return str_contains($e->getMessage(), '/storage/framework/views/'); + }; + + $exceptions->report(function (Throwable $e) use ($isStaleLivewireAsset, $isStaleCompiledView) { if ($isStaleLivewireAsset($e, request())) { return false; } + + if ($isStaleCompiledView($e)) { + return false; + } }); - $exceptions->render(function (Throwable $e, Request $request) use ($isStaleLivewireAsset) { + $exceptions->render(function (Throwable $e, Request $request) use ($isStaleLivewireAsset, $isStaleCompiledView) { if ($isStaleLivewireAsset($e, $request)) { return response('', 404); } + if ($isStaleCompiledView($e)) { + return response('', 503)->header('Retry-After', '5'); + } + return null; }); })->create(); diff --git a/tests/Feature/StaleCompiledViewTest.php b/tests/Feature/StaleCompiledViewTest.php new file mode 100644 index 0000000..b318d45 --- /dev/null +++ b/tests/Feature/StaleCompiledViewTest.php @@ -0,0 +1,46 @@ +get('/_test/stale-compiled-view'); + + $response->assertStatus(503); + expect($response->headers->get('Retry-After'))->toBe('5'); +}); + +it('does not report missing compiled view exceptions to the logs', function () { + Log::spy(); + + Route::get('/_test/stale-compiled-view-log', function () { + throw new FileNotFoundException( + 'File does not exist at path /var/www/html/storage/framework/views/livewire/views/abc123.blade.php.' + ); + }); + + $this->get('/_test/stale-compiled-view-log')->assertStatus(503); + + Log::shouldNotHaveReceived('error'); + Log::shouldNotHaveReceived('critical'); + Log::shouldNotHaveReceived('emergency'); +}); + +it('still reports FileNotFoundException for unrelated paths', function () { + Route::get('/_test/unrelated-missing-file', function () { + throw new FileNotFoundException( + 'File does not exist at path /var/www/html/storage/app/some-upload.pdf.' + ); + }); + + $response = $this->get('/_test/unrelated-missing-file'); + + expect($response->status())->not->toBe(503); +});