diff --git a/code/espurna/static/index.all.html.ipp b/code/espurna/static/index.all.html.ipp
index 47c1b6d4..4119c4d1 100644
--- a/code/espurna/static/index.all.html.ipp
+++ b/code/espurna/static/index.all.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0x68,0xeb,0x52,0xc2,0x76,0x35,0xe6,0x76,0xb0,0xf1,0xc4,0x55,0x17,0x26,0xdb,0x86,0xbd,0xde,0xac,
0x02,0x4c,0xd4,0xdd,0x4f,0xb8,0xc0,0x3c,0x0b,0x3b,0xf4,0x66,0x15,0x9a,0x82,0x6e,0x1f,0xe7,0x01,0x55,
diff --git a/code/espurna/static/index.curtain.html.ipp b/code/espurna/static/index.curtain.html.ipp
index 26c7ffb8..dbff7909 100644
--- a/code/espurna/static/index.curtain.html.ipp
+++ b/code/espurna/static/index.curtain.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0xea,0xe4,0x31,0xe1,0x8e,0x77,0x3b,0x48,0x08,0xa8,0x7a,0xa0,0x40,0xb9,0x7d,0x84,0xdb,0x01,0x8a,
0x48,0x74,0x37,0xa2,0x84,0x1d,0x7b,0x14,0xd0,0x1d,0x1a,0x0a,0x89,0x7c,0x1c,0x50,0x3d,0x27,0xd0,0x21,
diff --git a/code/espurna/static/index.garland.html.ipp b/code/espurna/static/index.garland.html.ipp
index d72fb30c..4b1e8589 100644
--- a/code/espurna/static/index.garland.html.ipp
+++ b/code/espurna/static/index.garland.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0xb6,0xdb,0x31,0x3b,0xd0,0xc2,0xc6,0x41,0x06,0x60,0x6b,0x30,0xe1,0x8e,0xc2,0xc6,0x01,0x6b,0xf0,
0x98,0xd7,0xac,0x84,0x1d,0xfb,0x00,0x9c,0x07,0x07,0xe9,0x1d,0x6f,0x32,0x40,0xf5,0x9e,0x9c,0x8a,0x0c,
diff --git a/code/espurna/static/index.light.html.ipp b/code/espurna/static/index.light.html.ipp
index fef898e3..17729577 100644
--- a/code/espurna/static/index.light.html.ipp
+++ b/code/espurna/static/index.light.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0x13,0x6a,0x52,0xc3,0x8e,0xbd,0x28,0x6e,0x07,0x8f,0x6c,0xa7,0xde,0xc1,0x82,0xe9,0x36,0x1f,0xe4,
0x76,0x10,0x35,0xe6,0xcf,0x79,0xa5,0x86,0xdd,0xc4,0x06,0xce,0xc3,0x81,0xf0,0xee,0x2d,0x2d,0xa0,0xaa,
diff --git a/code/espurna/static/index.lightfox.html.ipp b/code/espurna/static/index.lightfox.html.ipp
index 282ee58c..e31dbbba 100644
--- a/code/espurna/static/index.lightfox.html.ipp
+++ b/code/espurna/static/index.lightfox.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0xd7,0xda,0x51,0xb0,0x6d,0xd2,0xbb,0x1d,0x24,0x02,0xa9,0x7f,0x60,0x76,0xa0,0xf5,0x38,0x00,0x3c,
0xde,0xea,0xc0,0xe0,0x66,0x28,0xb8,0x1d,0xd8,0xb1,0xf3,0x2a,0xe5,0x02,0xaa,0x9e,0x8b,0x1b,0x63,0x40,
diff --git a/code/espurna/static/index.rfbridge.html.ipp b/code/espurna/static/index.rfbridge.html.ipp
index 3b3c88e6..b57697ea 100644
--- a/code/espurna/static/index.rfbridge.html.ipp
+++ b/code/espurna/static/index.rfbridge.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0x72,0xe6,0x31,0xe1,0x0e,0xc3,0xc6,0xc1,0xc6,0xc0,0xd6,0x42,0xd1,0x81,0x18,0x74,0x07,0xd8,0x42,
0x91,0xa7,0x40,0x94,0xb0,0x5d,0x0d,0xbb,0x1d,0xf4,0x9e,0x6d,0x5d,0x08,0xa0,0x7a,0x2f,0x4e,0xe4,0x2a,
diff --git a/code/espurna/static/index.rfm69.html.ipp b/code/espurna/static/index.rfm69.html.ipp
index 50e9fd39..9ff0664a 100644
--- a/code/espurna/static/index.rfm69.html.ipp
+++ b/code/espurna/static/index.rfm69.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0x37,0xe7,0x31,0xe1,0x0e,0xc3,0xc6,0xc1,0xc6,0xc0,0xd6,0xc2,0xc8,0x40,0xa0,0x3b,0xc0,0xa9,0xa2,
0x3e,0xd5,0xef,0x00,0xde,0x74,0x4b,0xca,0xed,0xa0,0xf8,0xfc,0xf8,0x46,0x00,0xd5,0x7b,0x71,0x43,0x86,
diff --git a/code/espurna/static/index.sensor.html.ipp b/code/espurna/static/index.sensor.html.ipp
index 8f2bcd44..58d5ff13 100644
--- a/code/espurna/static/index.sensor.html.ipp
+++ b/code/espurna/static/index.sensor.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0x11,0x0b,0x52,0xc0,0x8d,0xe1,0x1a,0x36,0x0e,0x36,0x30,0xd6,0x16,0x2a,0x64,0xe7,0x6b,0x00,0xe5,
0x0d,0x3f,0xbb,0x1f,0x69,0x15,0xeb,0x92,0x07,0x64,0x73,0x5c,0x5b,0x91,0xde,0xac,0x48,0x23,0x0d,0xbf,
diff --git a/code/espurna/static/index.small.html.ipp b/code/espurna/static/index.small.html.ipp
index 791e59f3..386d259c 100644
--- a/code/espurna/static/index.small.html.ipp
+++ b/code/espurna/static/index.small.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0x0b,0xd6,0x31,0xe1,0x0e,0xc3,0xc6,0xc1,0xc6,0xc0,0xd6,0x42,0xd1,0x81,0x18,0x74,0x87,0xba,0x46,
0x84,0xae,0x12,0x07,0xc6,0xb6,0x0c,0x9a,0x41,0x77,0x24,0x9c,0xb8,0xab,0x85,0x61,0x40,0xf5,0x5e,0xdc,
diff --git a/code/espurna/static/index.thermostat.html.ipp b/code/espurna/static/index.thermostat.html.ipp
index f7172513..12bf57ea 100644
--- a/code/espurna/static/index.thermostat.html.ipp
+++ b/code/espurna/static/index.thermostat.html.ipp
@@ -1,7 +1,8 @@
#pragma once
#include
#include
-alignas(4) static constexpr char webui_content_encoding[] = "br";
+alignas(4) static constexpr char webui_last_modified[] PROGMEM = "Tue, 01 Apr 2025 00:16:24 GMT";
+alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "br";
alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {
0x5b,0x5a,0xe7,0x51,0xc0,0x8d,0xe1,0xda,0xed,0x20,0x01,0xa8,0xea,0x81,0xd9,0x88,0xd8,0xed,0xa0,0x1c,
0x7e,0xfb,0x85,0x94,0x19,0x70,0xb0,0x71,0x06,0x0c,0xd0,0xf7,0xc4,0x80,0xaa,0xf7,0xe2,0x86,0x0c,0xc1,
diff --git a/code/espurna/web.cpp b/code/espurna/web.cpp
index 52ef0f70..81b723b5 100644
--- a/code/espurna/web.cpp
+++ b/code/espurna/web.cpp
@@ -209,7 +209,6 @@ size_t RequestPrint::write(const uint8_t* data, size_t size) {
namespace {
-PROGMEM_STRING(LastModified, __DATE__ " " __TIME__ " GMT");
static constexpr size_t WebConfigBufferMax { 4096 };
// server instance can't (yet) be static, port is the ctor argument :/
@@ -471,7 +470,7 @@ void _onHome(AsyncWebServerRequest *request) {
if (request->hasHeader(FPSTR(IfModifiedSince))) {
const auto value = request->header(FPSTR(IfModifiedSince));
- if (strncmp_P(value.c_str(), LastModified, value.length()) == 0) {
+ if (strncmp_P(value.c_str(), webui_last_modified, value.length()) == 0) {
request->send(304);
return;
}
@@ -496,11 +495,14 @@ void _onHome(AsyncWebServerRequest *request) {
auto* response = request->beginResponse_P(200, F("text/html"), webui_data, std::size(webui_data));
#endif
- if (__builtin_strlen(webui_content_encoding) != 0) {
- response->addHeader(F("Content-Encoding"), webui_content_encoding);
+ constexpr auto content_encoding = espurna::StringView(webui_content_encoding);
+ if (content_encoding.length()) {
+ response->addHeader(F("Content-Encoding"), content_encoding.toString());
}
- response->addHeader(F("Last-Modified"), FPSTR(LastModified));
+ constexpr auto last_modified = espurna::StringView(webui_last_modified);
+ response->addHeader(F("Last-Modified"), last_modified.toString());
+
response->addHeader(F("X-XSS-Protection"), F("1; mode=block"));
response->addHeader(F("X-Content-Type-Options"), F("nosniff"));
response->addHeader(F("X-Frame-Options"), F("deny"));
diff --git a/code/gulpfile.mjs b/code/gulpfile.mjs
index 40af49ea..69c1ef02 100644
--- a/code/gulpfile.mjs
+++ b/code/gulpfile.mjs
@@ -332,6 +332,14 @@ function formatBufferLines(buffer, every = 20) {
return lines.join(',\n');
}
+/**
+ * @param {File} file
+ * @returns {string}
+ */
+function formatLastModified(file) {
+ return (file?.stat?.mtime ?? (new Date())).toUTCString()
+}
+
/**
* generates c++-friendly output from the stream contents
* @param {BuildOptions} options
@@ -351,7 +359,8 @@ function toOutput(options) {
'#pragma once',
'#include ',
'#include ',
- `alignas(4) static constexpr char webui_content_encoding[] = "${options.compress || ''}";`,
+ `alignas(4) static constexpr char webui_last_modified[] PROGMEM = "${formatLastModified(source)}";`,
+ `alignas(4) static constexpr char webui_content_encoding[] PROGMEM = "${options.compress || ''}";`,
'alignas(4) static constexpr uint8_t webui_data[] PROGMEM = {',
formatBufferLines(source.contents),
'};\n'
@@ -384,15 +393,19 @@ function toOutput(options) {
* @returns {Transform}
*/
function adjustFileStat() {
+ const now = new Date();
+
return new Transform({
objectMode: true,
transform(source, _, callback) {
- if (source.stat) {
- const now = new Date();
- source.stat.atime = now;
- source.stat.mtime = now;
- source.stat.ctime = now;
+ if (!source.stat) {
+ source.stat = {};
}
+
+ source.stat.atime = now;
+ source.stat.mtime = now;
+ source.stat.ctime = now;
+
callback(null, source);
}});
}