diff --git a/config/static_caching.php b/config/static_caching.php
index e190b9729d..8b11db0978 100644
--- a/config/static_caching.php
+++ b/config/static_caching.php
@@ -125,7 +125,7 @@
'nocache' => 'cache',
- 'nocache_js_position' => 'body',
+ 'decouple_nocache_scripts' => false,
/*
|--------------------------------------------------------------------------
diff --git a/routes/web.php b/routes/web.php
index 5f2755063f..5b0231d81f 100755
--- a/routes/web.php
+++ b/routes/web.php
@@ -19,7 +19,8 @@
use Statamic\Http\Middleware\AuthGuard;
use Statamic\Http\Middleware\CP\AuthGuard as CPAuthGuard;
use Statamic\Statamic;
-use Statamic\StaticCaching\NoCache\Controller as NoCacheController;
+use Statamic\StaticCaching\NoCache\CsrfTokenController;
+use Statamic\StaticCaching\NoCache\NoCacheController;
use Statamic\StaticCaching\NoCache\NoCacheLocalize;
Route::name('statamic.')->group(function () {
@@ -49,14 +50,16 @@
Route::post('activate', [ActivateAccountController::class, 'reset'])->name('account.activate.action');
});
+ Route::post('nocache', NoCacheController::class)
+ ->middleware(NoCacheLocalize::class)
+ ->withoutMiddleware(['App\Http\Middleware\VerifyCsrfToken', 'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken']);
+
+ Route::post('csrf', CsrfTokenController::class)
+ ->withoutMiddleware(['App\Http\Middleware\VerifyCsrfToken', 'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken']);
+
Statamic::additionalActionRoutes();
});
- Route::prefix(config('statamic.routes.action'))
- ->post('nocache', NoCacheController::class)
- ->middleware(NoCacheLocalize::class)
- ->withoutMiddleware(['App\Http\Middleware\VerifyCsrfToken', 'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken']);
-
if (OAuth::enabled()) {
Route::get(config('statamic.oauth.routes.login'), [OAuthController::class, 'redirectToProvider'])->name('oauth.login');
Route::match(['get', 'post'], config('statamic.oauth.routes.callback'), [OAuthController::class, 'handleProviderCallback'])
diff --git a/src/Facades/StaticCache.php b/src/Facades/StaticCache.php
index df7aadc73a..47055c044e 100644
--- a/src/Facades/StaticCache.php
+++ b/src/Facades/StaticCache.php
@@ -16,6 +16,7 @@
* @method static ApplicationCacher createApplicationDriver(array $config)
* @method static \Illuminate\Cache\Repository cacheStore()
* @method static void flush()
+ * @method static void csrfTokenJs(string $js)
* @method static void nocacheJs(string $js)
* @method static void nocachePlaceholder(string $placeholder)
* @method static void includeJs()
diff --git a/src/StaticCaching/Cachers/FileCacher.php b/src/StaticCaching/Cachers/FileCacher.php
index 0a0a594b81..f0bf9329bd 100644
--- a/src/StaticCaching/Cachers/FileCacher.php
+++ b/src/StaticCaching/Cachers/FileCacher.php
@@ -26,6 +26,11 @@ class FileCacher extends AbstractCacher
*/
private $shouldOutputJs = false;
+ /**
+ * @var string
+ */
+ private $csrfTokenJs;
+
/**
* @var string
*/
@@ -196,16 +201,107 @@ private function isLongQueryStringPath($path)
return Str::contains($path, '_lqs_');
}
+ public function setCsrfTokenJs(string $js)
+ {
+ $this->csrfTokenJs = $js;
+ }
+
public function setNocacheJs(string $js)
{
$this->nocacheJs = $js;
}
- public function getNocacheJs(): string
+ public function getCsrfTokenJs(): string
{
$csrfPlaceholder = CsrfTokenReplacer::REPLACEMENT;
$default = <<
', '', $contents); } $contents = str_replace('NOCACHE_PLACEHOLDER', $cacher->getNocachePlaceholder(), $contents); $response->setContent($contents); } - - private function insertPosition() - { - return config('statamic.static_caching.nocache_js_position', 'body'); - } - - private function insertJsInHead($contents, $cacher) - { - $insertBefore = collect([ - Str::position($contents, ''), - ])->filter()->min(); - - $js = ""; - - return Str::substrReplace($contents, $js, $insertBefore, 0); - } - - private function insertJsInBody($contents, $cacher) - { - $js = $cacher->getNocacheJs(); - - return str_replace('', '', $contents); - } } diff --git a/src/StaticCaching/StaticCacheManager.php b/src/StaticCaching/StaticCacheManager.php index 9af77ab541..4fb2716de0 100644 --- a/src/StaticCaching/StaticCacheManager.php +++ b/src/StaticCaching/StaticCacheManager.php @@ -101,6 +101,11 @@ private function flushNocache() $this->cacheStore()->forget('nocache::urls'); } + public function csrfTokenJs(string $js) + { + $this->fileDriver()->setCsrfTokenJs($js); + } + public function nocacheJs(string $js) { $this->fileDriver()->setNocacheJs($js); diff --git a/tests/StaticCaching/FullMeasureStaticCachingTest.php b/tests/StaticCaching/FullMeasureStaticCachingTest.php index ed31ae1425..01f7c67550 100644 --- a/tests/StaticCaching/FullMeasureStaticCachingTest.php +++ b/tests/StaticCaching/FullMeasureStaticCachingTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\Attributes\Test; use Statamic\Facades\File; use Statamic\Facades\StaticCache; +use Statamic\StaticCaching\Cacher; use Statamic\StaticCaching\NoCache\Session; use Tests\FakesContent; use Tests\FakesViews; @@ -157,4 +158,36 @@ public function it_should_add_the_javascript_if_there_is_a_csrf_token() '', ]), file_get_contents($this->dir.'/about_.html')); } + + #[Test] + public function it_decouples_csrf_and_nocache_scripts_if_option_is_enabled() + { + $this->app['config']->set('statamic.static_caching.decouple_nocache_scripts', true); + + $this->withFakeViews(); + $this->viewShouldReturnRaw('layout', '