summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Brill <opensource@christophbrill.de>2026-08-03 00:44:38 +0200
committerChristoph Brill <opensource@christophbrill.de>2026-08-03 00:44:38 +0200
commit94906c9add9427002eaa9d1e7c3bdbf50291399d (patch)
tree538936352a297e23411ee12eca2c2badf257da24
parent159752fcc4c6a889d89111a529d514f3d4960f1a (diff)
Answer from the browser cache while the log is unchanged
-rw-r--r--common.inc.php47
-rwxr-xr-xindex.php14
-rwxr-xr-xjson.php12
3 files changed, 73 insertions, 0 deletions
diff --git a/common.inc.php b/common.inc.php
index 95747d9..39af7ad 100644
--- a/common.inc.php
+++ b/common.inc.php
@@ -86,6 +86,53 @@ function validDate($date)
}
/**
+ * Answer the request from the browser cache if the log did not change
+ *
+ * The logs of past days never change, and the log of the current day only ever
+ * grows, so its modification time and size identify the content. Everything
+ * that changes the rendering (the channel, the display options, ...) has to be
+ * part of $variant, otherwise a cached response would be reused for a request
+ * that renders something else.
+ *
+ * Sends the caching headers and, if the browser already has the current
+ * version, terminates the request with '304 Not Modified'.
+ *
+ * @param string $filename the log file the response is rendered from
+ * @param string $variant everything besides the log that affects the output
+ *
+ * @return void
+ */
+function cacheOnLog($filename, $variant)
+{
+ // A missing log may show up at any time, so do not let it be cached
+ if (!is_file($filename)) {
+ header('Cache-Control: no-cache');
+ return;
+ }
+
+ $mtime = filemtime($filename);
+ $etag = '"'.md5($mtime.'-'.filesize($filename).'-'.$variant).'"';
+
+ header('ETag: '.$etag);
+ header('Last-Modified: '.gmdate('D, d M Y H:i:s', $mtime).' GMT');
+ // Today's log still grows, so always revalidate instead of serving a stale
+ // response from the cache without asking
+ header('Cache-Control: no-cache');
+
+ $since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
+ ? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
+ $match = isset($_SERVER['HTTP_IF_NONE_MATCH'])
+ ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : false;
+
+ // The ETag is the authoritative check, only fall back to the timestamp if
+ // the browser did not send one
+ if ($match !== false ? $match === $etag : ($since !== false && $since >= $mtime)) {
+ header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
+ exit;
+ }
+}
+
+/**
* Read a log file line by line
*
* Reading the whole log using file() keeps every single line in memory at once,
diff --git a/index.php b/index.php
index 8586212..6b9a9e3 100755
--- a/index.php
+++ b/index.php
@@ -57,6 +57,20 @@ if (isset($_GET['highlight_names'])) {
);
}
+// Let the browser reuse its copy as long as the log did not change. The
+// variant covers everything besides the log that ends up in the HTML.
+if (isset($date)) {
+ cacheOnLog(
+ LOG_DIR.'dri-devel-'.$date.'.log',
+ implode(
+ '|', array(
+ $channel, $date, $show_html, $show_joins, $show_irssi,
+ $highlight_names,
+ )
+ )
+ );
+}
+
$colors = array('#009900', '#CC3300', '#330099', '#FF6600', '#CC33CC', '#66CCCC', '#FF0066', '#9900FF', '#00FFCC', '#6600FF');
echo '<!DOCTYPE html>
diff --git a/json.php b/json.php
index 817b272..8103b51 100755
--- a/json.php
+++ b/json.php
@@ -43,6 +43,18 @@ $filename = 'dri-devel-'.$date.'.log';
header("Content-type: application/json;");
+// Let the browser reuse its copy as long as the log did not change. 'maxdate'
+// is part of the variant because it rolls over at midnight.
+cacheOnLog(
+ LOG_DIR.$filename,
+ implode(
+ '|', array(
+ $channel, $date, validDate('today'), $_GET['mode'],
+ isset($_GET['users']) ? $_GET['users'] : '',
+ )
+ )
+);
+
$retval = array();
$retval['maxdate'] = validDate('today');
$retval['channel'] = $channel;