From 36f305743f36164cfcddfa86dd63b22c6556d40b Mon Sep 17 00:00:00 2001 From: Andreas Pattynama Date: Mon, 23 Mar 2020 17:09:54 +0100 Subject: [PATCH 1/5] Enable .json file extension for json responses To automatically set the correct content-type for application/json responses, check if the response is a JsonResponse and if so, create a .json file instead of a .html file --- readme.md | 4 +++- src/Cache.php | 25 +++++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/readme.md b/readme.md index 3493d2b..dbeb95c 100644 --- a/readme.md +++ b/readme.md @@ -89,7 +89,7 @@ In order to serve the static files directly once they've been cached, you need t } location / { - try_files $uri $uri/ /page-cache/$uri.html /index.php?$query_string; + try_files $uri $uri/ /page-cache/$uri.html /page-cache/$uri.json /index.php?$query_string; } ``` @@ -104,6 +104,8 @@ In order to serve the static files directly once they've been cached, you need t RewriteRule .? page-cache/pc__index__pc.html [L] RewriteCond %{DOCUMENT_ROOT}/page-cache%{REQUEST_URI}.html -f RewriteRule . page-cache%{REQUEST_URI}.html [L] + RewriteCond %{DOCUMENT_ROOT}/page-cache%{REQUEST_URI}.json -f + RewriteRule . page-cache%{REQUEST_URI}.json [L] ``` ### Ignoring the cached files diff --git a/src/Cache.php b/src/Cache.php index cf511b3..030eb58 100644 --- a/src/Cache.php +++ b/src/Cache.php @@ -5,6 +5,7 @@ use Exception; use Illuminate\Filesystem\Filesystem; use Illuminate\Contracts\Container\Container; +use Illuminate\Http\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -150,7 +151,7 @@ public function shouldCache(Request $request, Response $response) */ public function cache(Request $request, Response $response) { - list($path, $file) = $this->getDirectoryAndFileNames($request); + list($path, $file) = $this->getDirectoryAndFileNames($request, $response); $this->files->makeDirectory($path, 0775, true, true); @@ -169,7 +170,7 @@ public function cache(Request $request, Response $response) */ public function forget($slug) { - return $this->files->delete($this->getCachePath($slug.'.html')); + return $this->files->delete($this->getCachePath($slug.'.html')) || $this->files->delete($this->getCachePath($slug.'.json')); } /** @@ -186,13 +187,14 @@ public function clear() * Get the names of the directory and file. * * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Response $response * @return array */ - protected function getDirectoryAndFileNames($request) + protected function getDirectoryAndFileNames($request, $response) { $segments = explode('/', ltrim($request->getPathInfo(), '/')); - $file = $this->aliasFilename(array_pop($segments)).'.html'; + $file = $this->aliasFilename(array_pop($segments)) . '.' . $this->determineFileExtension($response); return [$this->getCachePath(implode('/', $segments)), $file]; } @@ -219,4 +221,19 @@ protected function getDefaultCachePath() return $this->container->make('path.public').'/page-cache'; } } + + /** + * Determine file extension + * + * @return string + */ + protected function determineFileExtension($response) + { + if ($response instanceof JsonResponse) { + return 'json'; + } + + return 'html'; + } + } From a6f0c74066c518c3e66f95a20f18cf6ae893b5a7 Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Sun, 19 Jul 2020 14:03:15 -0400 Subject: [PATCH 2/5] Delete both HTML and JSON files --- src/Cache.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Cache.php b/src/Cache.php index 030eb58..1e4134d 100644 --- a/src/Cache.php +++ b/src/Cache.php @@ -170,7 +170,10 @@ public function cache(Request $request, Response $response) */ public function forget($slug) { - return $this->files->delete($this->getCachePath($slug.'.html')) || $this->files->delete($this->getCachePath($slug.'.json')); + $deletedHtml = $this->files->delete($this->getCachePath($slug.'.html')); + $deletedJson = $this->files->delete($this->getCachePath($slug.'.json')); + + return $deletedHtml || $deletedJson; } /** From e0de38b9f05f5c0c5a38574a31d220104cf4827b Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Sun, 19 Jul 2020 14:10:35 -0400 Subject: [PATCH 3/5] Touchups --- src/Cache.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Cache.php b/src/Cache.php index 1e4134d..f41ab00 100644 --- a/src/Cache.php +++ b/src/Cache.php @@ -3,9 +3,9 @@ namespace Silber\PageCache; use Exception; +use Illuminate\Http\JsonResponse; use Illuminate\Filesystem\Filesystem; use Illuminate\Contracts\Container\Container; -use Illuminate\Http\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -197,7 +197,10 @@ protected function getDirectoryAndFileNames($request, $response) { $segments = explode('/', ltrim($request->getPathInfo(), '/')); - $file = $this->aliasFilename(array_pop($segments)) . '.' . $this->determineFileExtension($response); + $filename = $this->aliasFilename(array_pop($segments)); + $extension = $this->guessFileExtension($response); + + $file = "{$filename}.{$extension}"; return [$this->getCachePath(implode('/', $segments)), $file]; } @@ -226,11 +229,13 @@ protected function getDefaultCachePath() } /** - * Determine file extension + * Guess the correct file extension for the given response. + * + * Currently, only JSON and HTML are supported. * * @return string */ - protected function determineFileExtension($response) + protected function guessFileExtension($response) { if ($response instanceof JsonResponse) { return 'json'; From 7a9c0fb6e1d308382611e787c17f3e3d8f4d59c8 Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Sun, 19 Jul 2020 14:23:58 -0400 Subject: [PATCH 4/5] Use Symfony's `JsonResponse` --- src/Cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cache.php b/src/Cache.php index f41ab00..c4fafc3 100644 --- a/src/Cache.php +++ b/src/Cache.php @@ -3,11 +3,11 @@ namespace Silber\PageCache; use Exception; -use Illuminate\Http\JsonResponse; use Illuminate\Filesystem\Filesystem; use Illuminate\Contracts\Container\Container; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\JsonResponse; class Cache { From dfad052418ab69044378666e90a242971686ddc8 Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Sun, 19 Jul 2020 14:24:08 -0400 Subject: [PATCH 5/5] Add test for JSON responses --- tests/CacheTest.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/CacheTest.php b/tests/CacheTest.php index 6ccbdc6..6ab6fdb 100644 --- a/tests/CacheTest.php +++ b/tests/CacheTest.php @@ -10,6 +10,7 @@ use Illuminate\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\JsonResponse; class CacheTest extends TestCase { @@ -140,6 +141,23 @@ public function testCachesRootToSpecialFilename() $this->cache->cache(Request::create('/', 'GET'), Response::create('content')); } + public function testCachesJsonResponsesWithJsonExtension() + { + $content = ['this' => 'is', 'json' => [1, 2, 3]]; + + $this->files->shouldReceive('makeDirectory')->once() + ->with('page-cache', 0775, true, true); + + $this->files->shouldReceive('put')->once() + ->with('page-cache/get-json.json', json_encode($content), true); + + $this->cache->setCachePath('page-cache'); + $this->cache->cache( + Request::create('get-json', 'GET'), + JsonResponse::create($content) + ); + } + /** * Assert that the given request/response pair are cached. *