From 14a20dcb0eae75e6096ec966c9fed6dcc1283993 Mon Sep 17 00:00:00 2001 From: Malf Furious Date: Thu, 1 Nov 2018 23:02:23 -0400 Subject: Instruct client to cache df.php resources Since content served by df.php is inherently dynamic, the server wisely instructs clients to not cache any responses. In pratice, for Scrott, the resources accessible by df.php are usually static, perhaps only ocasionally appearing or disappearing. A consequence of this is that clients have to repeatedly download several images, often on each page load of the app. Low-bandwidth clients will especially feel this. This patch _explicitly_ inserts from headers into the response from df.php which instruct the client to keep a copy of the resource for 24 hours. The idea being that resource requests will be *drastically* reduced and if someone updates their head image (for example), that change will take no-more-than 1 day to propagate. Signed-off-by: Malf Furious --- app/df.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/df.php b/app/df.php index 80aec5a..c6e45fd 100644 --- a/app/df.php +++ b/app/df.php @@ -31,7 +31,8 @@ require_once "class/mesg.class.php"; /* * Serve the resource at the given URI in response to the current * request. When finished, this function will exit PHP and terminate - * this script. + * this script. The response instructs the client to cache the + * result for 24 hours. */ function serveResource(string $uri, ?string $filename = NULL) : void { @@ -40,8 +41,14 @@ function serveResource(string $uri, ?string $filename = NULL) : void if (!$f) exit; + $cachelen = 86400; // secs, 24-hours + $cachedate = gmdate("D, d M Y H:i:s", time() + $cachelen); + header("Content-Type: " . mime_content_type($uri)); header("Content-Length: " . filesize($uri)); + header("Expires: " . $cachedate); + header("Cache-Control: max-age=" . $cachelen); + header("Pragma: cache"); if ($filename) header("Content-Disposition: attachment; filename=\"" . $filename . "\""); -- cgit v1.2.3 From 4586d033f6cfdd9df6f1036ced25dd202b462aaa Mon Sep 17 00:00:00 2001 From: Malf Furious Date: Sun, 24 Mar 2019 01:12:21 -0400 Subject: Employ df cache validation using HTTP ETag header This patch is a direct improvement on the previous one. Now, instead of telling clients to always cache df resources for 24 hours before revalidating the file, we tell them to cache it for zero seconds. This, in cobination with the ETag header, prompts the browser to utilize the If-None-Match request header. When serving df resources, we will set an ETag, which is a sha256 of the file content for the browser to cache. When the browser wants to load a resource a second time, it will send the ETag back via the If-None-Match header so we can compare it to the current file's hash. If the browser's ETag is still current, we can return 304 and save some bandwidth. Otherwise, the full response is sent as usual. Signed-off-by: Malf Furious --- app/df.php | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/app/df.php b/app/df.php index c6e45fd..348daa2 100644 --- a/app/df.php +++ b/app/df.php @@ -31,24 +31,34 @@ require_once "class/mesg.class.php"; /* * Serve the resource at the given URI in response to the current * request. When finished, this function will exit PHP and terminate - * this script. The response instructs the client to cache the - * result for 24 hours. + * this script. */ function serveResource(string $uri, ?string $filename = NULL) : void { $f = fopen($uri, "rb"); + /* no file */ if (!$f) exit; - $cachelen = 86400; // secs, 24-hours - $cachedate = gmdate("D, d M Y H:i:s", time() + $cachelen); + /* enable client caching */ + header("Cache-Control: max-age=0"); + header("Pragma: cache"); + + $hash = hash_file("sha256", $uri); + /* validate client cache */ + if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && + $_SERVER['HTTP_IF_NONE_MATCH'] == $hash) + { + header("HTTP/1.1 304 Not Modified"); + exit; + } + + /* resource metadata */ header("Content-Type: " . mime_content_type($uri)); header("Content-Length: " . filesize($uri)); - header("Expires: " . $cachedate); - header("Cache-Control: max-age=" . $cachelen); - header("Pragma: cache"); + header("ETag: " . $hash); if ($filename) header("Content-Disposition: attachment; filename=\"" . $filename . "\""); -- cgit v1.2.3