Use gzip fallback for WebConfig clients
This commit is contained in:
1 parent
70d183a3ae
commit
22aa62e7d6
3 files changed
+2227
-7403
No files matched your search
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Pre-build script: Brotli-compress webui/index.html into a PROGMEM C header so the
|
||||
# Pre-build script: compress webui/index.html into a PROGMEM C header so the
|
||||
# webconfig portal can serve the page straight from flash with
|
||||
# Content-Encoding: br. The generated header is tracked so ESP32 targets
|
||||
# Content-Encoding: br or gzip. The generated header is tracked so ESP32 targets
|
||||
# that replace extra_scripts still compile from a clean checkout; this script
|
||||
# rewrites it only when the emitted firmware bytes actually change.
|
||||
#
|
||||
@@ -12,8 +12,8 @@
|
||||
#
|
||||
# Output: src/helpers/esp32/WebConfigHtml.h
|
||||
# WEBCONFIG_HTML_LOADER[] - small bootstrap page (PROGMEM)
|
||||
# WEBCONFIG_HTML_RAW[] - complete stripped page (PROGMEM)
|
||||
# WEBCONFIG_HTML_BR[] - complete Brotli-compressed page (PROGMEM)
|
||||
# WEBCONFIG_HTML_GZ[] - complete gzip-compressed page (PROGMEM)
|
||||
# WEBCONFIG_HTML_ETAG - quoted strong ETag for the loader page
|
||||
#
|
||||
# Runnable outside SCons to inspect exactly what gets shipped:
|
||||
@@ -21,6 +21,7 @@
|
||||
# or served directly by the mock backend with its --minify flag.
|
||||
|
||||
import hashlib
|
||||
import gzip
|
||||
import os
|
||||
import sys
|
||||
|
||||
@@ -92,6 +93,7 @@ def main():
|
||||
src_hash = content_hash(raw)
|
||||
|
||||
br = compress_html(raw)
|
||||
gz = gzip.compress(raw, compresslevel=9, mtime=0)
|
||||
version = hashlib.sha256(br).hexdigest()[:16]
|
||||
loader = ("<!doctype html><meta charset=utf-8><meta name=viewport "
|
||||
"content=\"width=device-width,initial-scale=1\"><title>MeshCore "
|
||||
@@ -112,24 +114,24 @@ def main():
|
||||
lines = []
|
||||
lines.append("// Auto-generated by scripts/generate_webconfig_html.py from %s" % SOURCE.replace(os.sep, "/"))
|
||||
lines.append("// DO NOT EDIT - edit webui/index.html instead.")
|
||||
lines.append("// Compressed with Google Brotli %s (quality %d, lgwin %d)." %
|
||||
lines.append("// Compressed with Google Brotli %s (quality %d, lgwin %d) and gzip." %
|
||||
(BROTLI_VERSION, QUALITY, LGWIN))
|
||||
lines.append("%s%s" % (HASH_MARKER, src_hash))
|
||||
lines.append("#pragma once")
|
||||
lines.append("#include <stdint.h>")
|
||||
lines.append("#include <pgmspace.h>")
|
||||
lines.append("")
|
||||
lines.append("const uint32_t WEBCONFIG_HTML_RAW_LEN = %d;" % len(raw))
|
||||
lines.append("const uint32_t WEBCONFIG_HTML_BR_LEN = %d;" % len(br))
|
||||
lines.append("const uint32_t WEBCONFIG_HTML_GZ_LEN = %d;" % len(gz))
|
||||
lines.append('const char WEBCONFIG_HTML_ETAG[] = "\\"%s\\"";' % etag)
|
||||
lines.append('const char WEBCONFIG_HTML_VERSION[] = "%s";' % version)
|
||||
lines.append("const uint16_t WEBCONFIG_HTML_LOADER_LEN = %d;" % len(loader_bytes))
|
||||
append_byte_array(lines, "WEBCONFIG_HTML_LOADER", loader_bytes)
|
||||
lines.append("")
|
||||
append_byte_array(lines, "WEBCONFIG_HTML_RAW", raw)
|
||||
lines.append("")
|
||||
append_byte_array(lines, "WEBCONFIG_HTML_BR", br)
|
||||
lines.append("")
|
||||
append_byte_array(lines, "WEBCONFIG_HTML_GZ", gz)
|
||||
lines.append("")
|
||||
|
||||
rendered = "\n".join(lines)
|
||||
try:
|
||||
@@ -143,8 +145,8 @@ def main():
|
||||
with open(OUTPUT, "w", encoding="utf-8", newline="") as f:
|
||||
f.write(rendered)
|
||||
|
||||
status("%s -> %s (%d bytes source, %d stripped, %d Brotli)"
|
||||
% (SOURCE, OUTPUT, len(src.encode("utf-8")), len(raw), len(br)))
|
||||
status("%s -> %s (%d bytes source, %d stripped, %d Brotli, %d gzip)"
|
||||
% (SOURCE, OUTPUT, len(src.encode("utf-8")), len(raw), len(br), len(gz)))
|
||||
|
||||
|
||||
# This script is attached only to esp32_base. Generate unconditionally here:
|
||||
|
||||
+2204
-7387
File diff suppressed because it is too large.
Load diff
@@ -1647,7 +1647,8 @@ void WebConfigServer::handleRoot(AsyncWebServerRequest* req) {
|
||||
req->send(res);
|
||||
}
|
||||
|
||||
static bool webConfigClientAcceptsBrotli(AsyncWebServerRequest* req) {
|
||||
static bool webConfigClientAcceptsEncoding(AsyncWebServerRequest* req,
|
||||
const char* wanted) {
|
||||
if (!req || !req->hasHeader("Accept-Encoding")) return false;
|
||||
String encodings = req->getHeader("Accept-Encoding")->value();
|
||||
encodings.toLowerCase();
|
||||
@@ -1660,7 +1661,7 @@ static bool webConfigClientAcceptsBrotli(AsyncWebServerRequest* req) {
|
||||
int semi = item.indexOf(';');
|
||||
String coding = semi < 0 ? item : item.substring(0, semi);
|
||||
coding.trim();
|
||||
if (coding == "br") {
|
||||
if (coding == wanted || coding == "*") {
|
||||
if (semi < 0) return true;
|
||||
String params = item.substring(semi + 1);
|
||||
params.trim();
|
||||
@@ -1686,7 +1687,7 @@ void WebConfigServer::handleUi(AsyncWebServerRequest* req) {
|
||||
return;
|
||||
}
|
||||
AsyncWebServerResponse* res = nullptr;
|
||||
if (webConfigClientAcceptsBrotli(req)) {
|
||||
if (webConfigClientAcceptsEncoding(req, "br")) {
|
||||
res = new WebConfigPacedProgmemResponse("text/html; charset=utf-8",
|
||||
WEBCONFIG_HTML_BR,
|
||||
WEBCONFIG_HTML_BR_LEN);
|
||||
@@ -1694,12 +1695,16 @@ void WebConfigServer::handleUi(AsyncWebServerRequest* req) {
|
||||
// precompressed bytes.
|
||||
res->addHeader("Content-Encoding", "br");
|
||||
res->addHeader("Cache-Control", "public, max-age=31536000, immutable");
|
||||
} else {
|
||||
// Never send Brotli to clients that did not advertise support for it.
|
||||
} else if (webConfigClientAcceptsEncoding(req, "gzip")) {
|
||||
res = new WebConfigPacedProgmemResponse("text/html; charset=utf-8",
|
||||
WEBCONFIG_HTML_RAW,
|
||||
WEBCONFIG_HTML_RAW_LEN);
|
||||
WEBCONFIG_HTML_GZ,
|
||||
WEBCONFIG_HTML_GZ_LEN);
|
||||
res->addHeader("Content-Encoding", "gzip");
|
||||
res->addHeader("Cache-Control", "no-cache");
|
||||
} else {
|
||||
req->send(406, "text/plain",
|
||||
"WebConfig requires Brotli or gzip support");
|
||||
return;
|
||||
}
|
||||
req->send(res);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user