Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions config/static_caching.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,19 @@

'warm_queue' => null,

/*
|--------------------------------------------------------------------------
| Shared Error Pages
|--------------------------------------------------------------------------
|
| You may choose to share the same statically generated error page across
| all errors. For example, the first time a 404 is encountered it will
| be generated and cached, and then served for all subsequent 404s.
|
| This is only supported for half measure.
|
*/

'share_errors' => false,

];
29 changes: 29 additions & 0 deletions src/Exceptions/Concerns/RendersHttpExceptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

namespace Statamic\Exceptions\Concerns;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Statamic\Facades\Cascade;
use Statamic\Statamic;
use Statamic\StaticCaching\Cacher;
use Statamic\StaticCaching\Cachers\ApplicationCacher;
use Statamic\View\View;

trait RendersHttpExceptions
Expand All @@ -18,6 +22,10 @@ public function render()
return response()->json(['message' => $this->getApiMessage()], $this->getStatusCode());
}

if ($cached = $this->getCachedError()) {
return $cached;
}

if (view()->exists('errors.'.$this->getStatusCode())) {
return response($this->contents(), $this->getStatusCode());
}
Expand Down Expand Up @@ -53,4 +61,25 @@ public function getApiMessage()
{
return $this->getMessage();
}

private function getCachedError(): ?Response
{
$status = $this->getStatusCode();

if (! config('statamic.static_caching.share_errors')) {
return null;
}

$cacher = app(Cacher::class);

if (! $cacher instanceof ApplicationCacher) {
return null;
}

$request = Request::createFrom(request())->fakeStaticCacheStatus($status);

return $cacher->hasCachedPage($request)
? $cacher->getCachedPage($request)->toResponse($request)
: null;
}
}
3 changes: 2 additions & 1 deletion src/StaticCaching/Cachers/ApplicationCacher.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public function cachePage(Request $request, $content)
$cacheValue = [
'content' => $value,
'headers' => $headers,
'status' => $event->response->getStatusCode(),
];

$this->getDefaultExpiration()
Expand Down Expand Up @@ -79,7 +80,7 @@ public function getCachedPage(Request $request)
{
$cachedPage = $this->cached ?? $this->getFromCache($request);

return new Page($cachedPage['content'], $cachedPage['headers']);
return new Page($cachedPage['content'], $cachedPage['headers'], $cachedPage['status'] ?? 200);
}

private function getFromCache(Request $request)
Expand Down
22 changes: 21 additions & 1 deletion src/StaticCaching/Middleware/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Statamic\Facades\File;
use Statamic\Statamic;
use Statamic\StaticCaching\Cacher;
use Statamic\StaticCaching\Cachers\ApplicationCacher;
use Statamic\StaticCaching\Cachers\NullCacher;
use Statamic\StaticCaching\NoCache\RegionNotFound;
use Statamic\StaticCaching\NoCache\Session;
Expand Down Expand Up @@ -63,6 +64,8 @@ public function handle($request, Closure $next)
if ($this->shouldBeCached($request, $response)) {
$lock->acquire(true);

$this->copyError($request, $response);

$this->makeReplacementsAndCacheResponse($request, $response);

$this->nocache->write();
Expand All @@ -73,6 +76,21 @@ public function handle($request, Closure $next)
return $response;
}

private function copyError($request, $response)
{
$status = $response->getStatusCode();

if (! config('statamic.static_caching.share_errors')) {
return;
}

$request = Request::createFrom($request)->fakeStaticCacheStatus($status);

if (! $this->cacher->hasCachedPage($request)) {
$this->cacher->cachePage($request, $response);
}
}

private function attemptToGetCachedResponse($request)
{
if ($this->canBeCached($request) && $this->cacher->hasCachedPage($request)) {
Expand Down Expand Up @@ -139,7 +157,9 @@ private function shouldBeCached($request, $response)
return false;
}

if ($response->getStatusCode() !== 200 || $response->getContent() == '') {
$statuses = $this->cacher instanceof ApplicationCacher ? [200, 404] : [200];

if (! in_array($response->getStatusCode(), $statuses) || $response->getContent() == '') {
return false;
}

Expand Down
9 changes: 6 additions & 3 deletions src/StaticCaching/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@

class Page implements Responsable
{
public function __construct(public string $content, public array $headers = [])
{
public function __construct(
public string $content,
public array $headers = [],
public int $status = 200
) {
}

public function toResponse($request): Response
{
return new Response($this->content, 200, $this->headers);
return new Response($this->content, $this->status, $this->headers);
}
}
9 changes: 9 additions & 0 deletions src/StaticCaching/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Statamic\StaticCaching;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
Expand Down Expand Up @@ -78,5 +79,13 @@ public function boot()
Blade::directive('nocache', function ($exp) {
return '<?php echo app("Statamic\StaticCaching\NoCache\BladeDirective")->handle('.$exp.', \Illuminate\Support\Arr::except(get_defined_vars(), [\'__data\', \'__path\'])); ?>';
});

Request::macro('fakeStaticCacheStatus', function (int $status) {
$url = '/__shared-errors/'.$status;
$this->pathInfo = $url;
$this->requestUri = $url;

return $this;
});
}
}
1 change: 1 addition & 0 deletions tests/StaticCaching/ApplicationCacherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function gets_cached_page()
$cachedPage = $cacher->getCachedPage($request);
$this->assertEquals('html content', $cachedPage->content);
$this->assertEquals('application/html', $cachedPage->headers['Content-Type']);
$this->assertEquals(200, $cachedPage->status);
}

/** @test */
Expand Down