From 67ae716c60b95e9f184b14798d366ec8248fcb23 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Tue, 12 Dec 2023 15:45:57 +0100 Subject: [PATCH] JSON HTTP error handling --- wled00/const.h | 3 ++- wled00/fcn_declare.h | 2 +- wled00/json.cpp | 6 +++--- wled00/wled_server.cpp | 16 ++++++++++++++-- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/wled00/const.h b/wled00/const.h index e47d57649..ef1b31c01 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -342,8 +342,9 @@ // WLED Error modes #define ERR_NONE 0 // All good :) #define ERR_DENIED 1 // Permission denied -#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?) OBSOLETE +#define ERR_CONCURRENCY 2 // Conurrency (client active) #define ERR_NOBUF 3 // JSON buffer was not released in time, request cannot be handled at this time +#define ERR_NOT_IMPL 4 // Not implemented #define ERR_JSON 9 // JSON parsing failed (input too large?) #define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?) #define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 810626d0c..ec7527269 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -399,10 +399,10 @@ bool isIp(String str); void createEditHandler(bool enable); bool captivePortal(AsyncWebServerRequest *request); void initServer(); -void serveIndexOrWelcome(AsyncWebServerRequest *request); void serveIndex(AsyncWebServerRequest* request); String msgProcessor(const String& var); void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& headl, const String& subl="", byte optionT=255); +void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t error); String dmxProcessor(const String& var); void serveSettings(AsyncWebServerRequest* request, bool post = false); void serveSettingsJS(AsyncWebServerRequest* request); diff --git a/wled00/json.cpp b/wled00/json.cpp index a91404cb2..bf274e3e0 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1012,7 +1012,7 @@ static volatile bool servingClient = false; void serveJson(AsyncWebServerRequest* request) { if (servingClient) { - request->send(503, "application/json", F("{\"error\":2}")); // ERR_CONCURENCY + serveJsonError(request, 503, ERR_CONCURRENCY); return; } servingClient = true; @@ -1044,13 +1044,13 @@ void serveJson(AsyncWebServerRequest* request) return; } else if (url.length() > 6) { //not just /json - request->send(501, "application/json", F("{\"error\":\"Not implemented\"}")); + serveJsonError(request, 501, ERR_NOT_IMPL); servingClient = false; return; } if (!requestJSONBufferLock(17)) { - request->send(503, "application/json", F("{\"error\":3}")); + serveJsonError(request, 503, ERR_NOBUF); servingClient = false; return; } diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index 4dbfa1909..db8eb4a02 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -183,7 +183,7 @@ void initServer() JsonObject root = doc.as(); if (error || root.isNull()) { releaseJSONBufferLock(); - request->send(400, "application/json", F("{\"error\":9}")); // ERR_JSON + serveJsonError(request, 400, ERR_JSON); return; } if (root.containsKey("pin")) checkSettingsPIN(root["pin"].as()); @@ -201,8 +201,8 @@ void initServer() verboseResponse = deserializeState(root); } else { if (!correctPIN && strlen(settingsPIN)>0) { - request->send(401, "application/json", F("{\"error\":1}")); // ERR_DENIED releaseJSONBufferLock(); + serveJsonError(request, 401, ERR_DENIED); return; } verboseResponse = deserializeConfig(root); //use verboseResponse to determine whether cfg change should be saved immediately @@ -509,6 +509,18 @@ void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& h } +void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t error) +{ + AsyncJsonResponse *response = new AsyncJsonResponse(64); + if (error < ERR_NOT_IMPL) response->addHeader("Retry-After", "1"); + response->setContentType("application/json"); + response->setCode(code); + JsonObject obj = response->getRoot(); + obj[F("error")] = error; + response->setLength(); + request->send(response); +} + #ifdef WLED_ENABLE_DMX String dmxProcessor(const String& var) {