From 7e358f36193d2a94d52d2c66393cf66c29de1cbe Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 10 Aug 2017 13:44:35 +0200 Subject: [PATCH 1/5] StaticController: Set a maximum age and honor no-cache for gravatar requests refs #2917 --- application/controllers/StaticController.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/application/controllers/StaticController.php b/application/controllers/StaticController.php index 222d8032d..5d127a646 100644 --- a/application/controllers/StaticController.php +++ b/application/controllers/StaticController.php @@ -31,19 +31,22 @@ class StaticController extends Controller public function gravatarAction() { $response = $this->getResponse(); - $response->setHeader('Pragma', 'cache') - ->setHeader('Cache-Control', 'public'); + $response->setHeader('Cache-Control', 'public, max-age=1814400, stale-while-revalidate=604800', true); + + $noCache = $this->getRequest()->getHeader('Cache-Control') === 'no-cache' + || $this->getRequest()->getHeader('Pragma') === 'no-cache'; $cache = FileCache::instance(); $filename = md5(strtolower(trim($this->getParam('email')))); $cacheFile = 'gravatar-' . $filename; - if ($etag = $cache->etagMatchesCachedFile($cacheFile)) { - $response->setHttpResponseCode(304); - return; - } - $response->setHeader('Content-Type', 'image/jpg'); - if ($cache->has($cacheFile)) { + if (! $noCache && $cache->has($cacheFile, time() - 1814400)) { + if ($cache->etagMatchesCachedFile($cacheFile)) { + $response->setHttpResponseCode(304); + return; + } + + $response->setHeader('Content-Type', 'image/jpg', true); $response->setHeader('ETag', sprintf('"%s"', $cache->etagForCachedFile($cacheFile))); $cache->send($cacheFile); return; From 30b752c72c2d2be0aa8fc790ee110ff2120e7e08 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 10 Aug 2017 13:46:09 +0200 Subject: [PATCH 2/5] StaticController: Set a maximum age and check E-Tags of module image requests refs #2917 --- application/controllers/StaticController.php | 25 ++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/application/controllers/StaticController.php b/application/controllers/StaticController.php index 5d127a646..57e7ce513 100644 --- a/application/controllers/StaticController.php +++ b/application/controllers/StaticController.php @@ -86,13 +86,24 @@ class StaticController extends Controller } $s = stat($filePath); - $this->getResponse() - ->setHeader('Pragma', 'cache') - ->setHeader('Content-Type', 'image/' . $extension) - ->setHeader('Cache-Control', 'public, max-age=3600') - ->setHeader('Last-Modified', gmdate('D, d M Y H:i:s', $s['mtime']) . ' GMT') - ->setHeader('ETag', sprintf('%x-%x-%x', $s['ino'], $s['size'], (float) str_pad($s['mtime'], 16, '0'))); + $eTag = sprintf('%x-%x-%x', $s['ino'], $s['size'], (float) str_pad($s['mtime'], 16, '0')); - readfile($filePath); + $this->getResponse()->setHeader( + 'Cache-Control', + 'public, max-age=1814400, stale-while-revalidate=604800', + true + ); + + if ($this->getRequest()->getServer('HTTP_IF_NONE_MATCH') === $eTag) { + $this->getResponse() + ->setHttpResponseCode(304); + } else { + $this->getResponse() + ->setHeader('ETag', $eTag) + ->setHeader('Content-Type', 'image/' . $extension, true) + ->setHeader('Last-Modified', gmdate('D, d M Y H:i:s', $s['mtime']) . ' GMT'); + + readfile($filePath); + } } } From 7b7bfb5a5d892411ed968049f1c1f460855a107c Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 22 Aug 2017 08:37:12 +0200 Subject: [PATCH 3/5] FileCache: Use the correct variable when checking a file's modification time refs #2917 --- library/Icinga/Web/FileCache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Web/FileCache.php b/library/Icinga/Web/FileCache.php index 1b9203e13..a64fadd22 100644 --- a/library/Icinga/Web/FileCache.php +++ b/library/Icinga/Web/FileCache.php @@ -99,7 +99,7 @@ class FileCache return true; } - $info = stat($file); + $info = stat($filename); if ($info === false) { return false; From 6702ccb2a73edee420d0a8066919345280865d61 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 22 Aug 2017 09:31:56 +0200 Subject: [PATCH 4/5] FileCache: Ignore compression suffix when checking cache made of multiple files refs #2917 --- library/Icinga/Web/FileCache.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/Icinga/Web/FileCache.php b/library/Icinga/Web/FileCache.php index a64fadd22..74f9d08f3 100644 --- a/library/Icinga/Web/FileCache.php +++ b/library/Icinga/Web/FileCache.php @@ -201,6 +201,11 @@ class FileCache return false; } + if (preg_match('/([0-9a-f]{8}-[0-9a-f]{8}-[0-9a-f]{8})-\w+/i', $match, $matches)) { + // Removes compression suffixes as our custom algorithm can't handle compressed cache files anyway + $match = $matches[1]; + } + $etag = self::etagForFiles($files); return $match === $etag ? $etag : false; } From beb3326631b53cbf02885a3fd8355a0f84708644 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 22 Aug 2017 09:33:28 +0200 Subject: [PATCH 5/5] StyleSheet/JavaScript: Also include Cache-Control when answering with a 304 Without Cache-Control, the browser may invalidate its cached file and we're serving the file again on the next request. refs #2917 --- library/Icinga/Web/JavaScript.php | 2 +- library/Icinga/Web/StyleSheet.php | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/library/Icinga/Web/JavaScript.php b/library/Icinga/Web/JavaScript.php index 76c25def8..75dd783d3 100644 --- a/library/Icinga/Web/JavaScript.php +++ b/library/Icinga/Web/JavaScript.php @@ -98,13 +98,13 @@ class JavaScript $request = Icinga::app()->getRequest(); $noCache = $request->getHeader('Cache-Control') === 'no-cache' || $request->getHeader('Pragma') === 'no-cache'; + header('Cache-Control: public'); if (! $noCache && FileCache::etagMatchesFiles($files)) { header("HTTP/1.1 304 Not Modified"); return; } else { $etag = FileCache::etagForFiles($files); } - header('Cache-Control: public'); header('ETag: "' . $etag . '"'); header('Content-Type: application/javascript'); diff --git a/library/Icinga/Web/StyleSheet.php b/library/Icinga/Web/StyleSheet.php index 549e11c5c..63eee3647 100644 --- a/library/Icinga/Web/StyleSheet.php +++ b/library/Icinga/Web/StyleSheet.php @@ -182,6 +182,7 @@ class StyleSheet $request = $styleSheet->app->getRequest(); $response = $styleSheet->app->getResponse(); + $response->setHeader('Cache-Control', 'public', true); $noCache = $request->getHeader('Cache-Control') === 'no-cache' || $request->getHeader('Pragma') === 'no-cache'; @@ -194,9 +195,7 @@ class StyleSheet $etag = FileCache::etagForFiles($styleSheet->lessCompiler->getLessFiles()); - $response - ->setHeader('Cache-Control', 'public', true) - ->setHeader('ETag', $etag, true) + $response->setHeader('ETag', $etag, true) ->setHeader('Content-Type', 'text/css', true); $cacheFile = 'icinga-' . $etag . ($minified ? '.min' : '') . '.css';