api: remove status cache validators
This commit is contained in:
-15
@@ -189,21 +189,6 @@ If an unknown field is requested, the Cargo ESP32 returns HTTP `400`:
|
|||||||
"details": ["Unknown field 'xyz'"]
|
"details": ["Unknown field 'xyz'"]
|
||||||
}
|
}
|
||||||
|
|
||||||
#### HTTP caching
|
|
||||||
|
|
||||||
`GET /api/v1/status` returns these cache validation headers:
|
|
||||||
|
|
||||||
ETag
|
|
||||||
Last-Modified
|
|
||||||
Cache-Control: no-cache
|
|
||||||
|
|
||||||
Clients may revalidate with `If-None-Match` or `If-Modified-Since`.
|
|
||||||
|
|
||||||
If the selected status payload has not changed, the Cargo ESP32 returns:
|
|
||||||
|
|
||||||
HTTP/1.1 304 Not Modified
|
|
||||||
|
|
||||||
A `304` response has no JSON body.
|
|
||||||
|
|
||||||
### battery
|
### battery
|
||||||
|
|
||||||
|
|||||||
@@ -1134,30 +1134,9 @@ int findStatusFieldIndex(const String& field) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fnv1a32(const String& value) {
|
|
||||||
uint32_t hash = 2166136261UL;
|
|
||||||
for (unsigned int i = 0; i < value.length(); i++) {
|
|
||||||
hash ^= static_cast<uint8_t>(value[i]);
|
|
||||||
hash *= 16777619UL;
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
String statusEtagForPayload(const String& payload) {
|
|
||||||
return String("\"") + String(fnv1a32(payload), HEX) + "-" + String(payload.length(), HEX) + "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
String lastStatusValidatorEtag = "";
|
|
||||||
String lastStatusModified = "Thu, 01 Jan 1970 00:00:00 GMT";
|
|
||||||
|
|
||||||
String formatHttpDateFromUptime(unsigned long seconds) {
|
|
||||||
char buffer[32];
|
|
||||||
snprintf(buffer, sizeof(buffer), "Thu, 01 Jan 1970 %02lu:%02lu:%02lu GMT",
|
|
||||||
(seconds / 3600UL) % 24UL,
|
|
||||||
(seconds / 60UL) % 60UL,
|
|
||||||
seconds % 60UL);
|
|
||||||
return String(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void buildStatusDocument(JsonDocument& doc) {
|
void buildStatusDocument(JsonDocument& doc) {
|
||||||
doc["type"] = MSG_STATUS_RESPONSE;
|
doc["type"] = MSG_STATUS_RESPONSE;
|
||||||
@@ -2737,34 +2716,6 @@ void handleStatus() {
|
|||||||
String output;
|
String output;
|
||||||
serializeJson(doc, output);
|
serializeJson(doc, output);
|
||||||
|
|
||||||
DynamicJsonDocument validatorDoc(4096);
|
|
||||||
deserializeJson(validatorDoc, output);
|
|
||||||
validatorDoc["timestamp"] = 0;
|
|
||||||
if (validatorDoc["system"].is<JsonObject>()) {
|
|
||||||
validatorDoc["system"]["uptime_seconds"] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
String validatorPayload;
|
|
||||||
serializeJson(validatorDoc, validatorPayload);
|
|
||||||
|
|
||||||
String etag = statusEtagForPayload(validatorPayload);
|
|
||||||
if (etag != lastStatusValidatorEtag) {
|
|
||||||
lastStatusValidatorEtag = etag;
|
|
||||||
lastStatusModified = formatHttpDateFromUptime(millis() / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
server.sendHeader("ETag", etag);
|
|
||||||
server.sendHeader("Last-Modified", lastStatusModified);
|
|
||||||
server.sendHeader("Cache-Control", "no-cache");
|
|
||||||
|
|
||||||
String ifNoneMatch = server.header("If-None-Match");
|
|
||||||
String ifModifiedSince = server.header("If-Modified-Since");
|
|
||||||
|
|
||||||
if (ifNoneMatch == etag || ifModifiedSince == lastStatusModified) {
|
|
||||||
server.send(304);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
server.send(200, "application/json", output);
|
server.send(200, "application/json", output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2869,9 +2820,6 @@ void setup() {
|
|||||||
server.on("/bms/select", HTTP_POST, handleSelectBms);
|
server.on("/bms/select", HTTP_POST, handleSelectBms);
|
||||||
|
|
||||||
|
|
||||||
const char* statusCacheHeaders[] = {"If-None-Match", "If-Modified-Since"};
|
|
||||||
server.collectHeaders(statusCacheHeaders, 2);
|
|
||||||
|
|
||||||
server.begin();
|
server.begin();
|
||||||
|
|
||||||
Serial.println("Web Server Started");
|
Serial.println("Web Server Started");
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ def test_http_error_fixture_and_known_error_codes_are_stable():
|
|||||||
assert error_code in source
|
assert error_code in source
|
||||||
|
|
||||||
|
|
||||||
def test_status_endpoint_supports_field_selection_and_cache_headers():
|
def test_status_endpoint_supports_field_selection():
|
||||||
source = firmware_source()
|
source = firmware_source()
|
||||||
|
|
||||||
assert 'server.hasArg("fields")' in source
|
assert 'server.hasArg("fields")' in source
|
||||||
@@ -293,13 +293,6 @@ def test_status_endpoint_supports_field_selection_and_cache_headers():
|
|||||||
assert '"invalid_field"' in source
|
assert '"invalid_field"' in source
|
||||||
assert 'Unknown field' in source
|
assert 'Unknown field' in source
|
||||||
assert 'server.send(400, "application/json", errorOutput)' in source
|
assert 'server.send(400, "application/json", errorOutput)' in source
|
||||||
assert 'server.sendHeader("ETag", etag)' in source
|
|
||||||
assert 'server.sendHeader("Last-Modified", lastStatusModified)' in source
|
|
||||||
assert 'server.sendHeader("Cache-Control", "no-cache")' in source
|
|
||||||
assert 'server.header("If-None-Match")' in source
|
|
||||||
assert 'server.header("If-Modified-Since")' in source
|
|
||||||
assert 'server.send(304)' in source
|
|
||||||
assert 'server.collectHeaders(statusCacheHeaders, 2)' in source
|
|
||||||
|
|
||||||
|
|
||||||
def test_embedded_webui_uses_partial_status_for_overview_polling():
|
def test_embedded_webui_uses_partial_status_for_overview_polling():
|
||||||
|
|||||||
Reference in New Issue
Block a user