Finalize implementation

This commit is contained in:
jpirnay
2026-04-13 20:24:28 +02:00
parent 1c3ba11563
commit a03d232dd3
7 changed files with 96 additions and 16 deletions
+29 -4
View File
@@ -31,6 +31,7 @@ esp_http_client_handle_t g_sessionClient = nullptr;
// the longest expected message including esp_err name (~32 chars), opcode (~10), heap
// numbers, and HTTP status. Single-threaded sync flow makes static safe.
char g_failureDetailBuf[160] = {0};
char g_lastResponsePreview[160] = {0};
std::string previewBody(const char* body, const size_t maxLen = 120) {
if (!body || !*body) {
@@ -56,6 +57,12 @@ std::string previewBody(const char* body, const size_t maxLen = 120) {
return preview;
}
void rememberResponsePreview(const char* body) {
const std::string preview = previewBody(body, sizeof(g_lastResponsePreview) - 1);
strncpy(g_lastResponsePreview, preview.c_str(), sizeof(g_lastResponsePreview) - 1);
g_lastResponsePreview[sizeof(g_lastResponsePreview) - 1] = '\0';
}
// Reset the static diagnostic state at the start of each request and capture pre-flight
// heap so failure reporting always reflects what was available when the request started.
void beginRequest(const char* operation) {
@@ -64,6 +71,7 @@ void beginRequest(const char* operation) {
KOReaderSyncClient::lastHttpCode = 0;
KOReaderSyncClient::lastHeapAtFailure = ESP.getFreeHeap();
KOReaderSyncClient::lastContigHeapAtFailure = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT);
g_lastResponsePreview[0] = '\0';
}
// Skip a leading UTF-8 BOM (EF BB BF) and ASCII whitespace, returning a pointer
@@ -475,7 +483,8 @@ KOReaderSyncClient::Error KOReaderSyncClient::getProgress(const std::string& doc
LOG_DBG("KOSync", "GET %s -> %d (err: %s) [attempt %d body_len=%u]", url.c_str(), httpCode, esp_err_to_name(err),
attempt, static_cast<unsigned>(bodyLen));
if (err == ESP_OK && (httpCode < 200 || httpCode >= 300)) {
LOG_ERR("KOSync", "GET failure body preview: %s", previewBody(activeBuf->data).c_str());
rememberResponsePreview(activeBuf->data);
LOG_ERR("KOSync", "GET failure body preview: %s", g_lastResponsePreview);
}
// Retry exactly once for connect-level failures only.
@@ -597,9 +606,10 @@ KOReaderSyncClient::Error KOReaderSyncClient::updateProgress(const KOReaderProgr
LOG_DBG("KOSync", "PUT %s -> %d (err: %s) [attempt %d body_len=%u]", url.c_str(), httpCode, esp_err_to_name(err),
attempt, static_cast<unsigned>(bodyLen));
if (err == ESP_OK && (httpCode < 200 || httpCode >= 300)) {
LOG_ERR("KOSync", "PUT failure body preview: %s", previewBody(activeBuf->data).c_str());
LOG_ERR("KOSync", "PUT failure request summary: document=%s percentage=%.4f progress=%s", progress.document.c_str(),
progress.percentage, progress.progress.c_str());
rememberResponsePreview(activeBuf->data);
LOG_ERR("KOSync", "PUT failure body preview: %s", g_lastResponsePreview);
LOG_ERR("KOSync", "PUT failure request summary: document=%s percentage=%.4f progress=%s",
progress.document.c_str(), progress.percentage, progress.progress.c_str());
}
// Retry exactly once for connect-level failures only.
@@ -670,6 +680,21 @@ const char* KOReaderSyncClient::lastFailureDetail() {
}
// Server case: got an HTTP status the client didn't recognize as success.
if (lastHttpCode != 0) {
if (lastHttpCode == 404 && lastOperation && strcmp(lastOperation, "update progress") == 0) {
std::string lowerPreview = g_lastResponsePreview;
std::transform(lowerPreview.begin(), lowerPreview.end(), lowerPreview.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
if (lowerPreview.find("book not found") != std::string::npos) {
snprintf(g_failureDetailBuf, sizeof(g_failureDetailBuf),
"%s: server does not know this book yet; server expects the same file to already exist there, usually "
"downloaded via OPDS",
lastOperation);
return g_failureDetailBuf;
}
snprintf(g_failureDetailBuf, sizeof(g_failureDetailBuf),
"%s: HTTP 404 (upload rejected; server may require book to be known)", lastOperation);
return g_failureDetailBuf;
}
snprintf(g_failureDetailBuf, sizeof(g_failureDetailBuf), "%s: HTTP %d", lastOperation, lastHttpCode);
return g_failureDetailBuf;
}