Save flash: Move WebApi json parsing to separate method to prevent a lot of redundant code

This commit is contained in:
Thomas Basler 2024-04-01 13:52:09 +02:00
parent 58efd9e954
commit 8add226a7c
13 changed files with 82 additions and 420 deletions

View File

@ -22,6 +22,7 @@
#include "WebApi_webapp.h"
#include "WebApi_ws_console.h"
#include "WebApi_ws_live.h"
#include <AsyncJson.h>
#include <ESPAsyncWebServer.h>
#include <TaskSchedulerDeclarations.h>
@ -37,6 +38,8 @@ public:
static void writeConfig(JsonVariant& retMsg, const WebApiError code = WebApiError::GenericSuccess, const String& message = "Settings saved!");
static bool parseRequestData(AsyncWebServerRequest* request, AsyncJsonResponse* response, DynamicJsonDocument& json_document, size_t max_document_size = 1024);
private:
AsyncWebServer _server;

View File

@ -85,4 +85,38 @@ void WebApiClass::writeConfig(JsonVariant& retMsg, const WebApiError code, const
}
}
bool WebApiClass::parseRequestData(AsyncWebServerRequest* request, AsyncJsonResponse* response, DynamicJsonDocument& json_document, size_t max_document_size)
{
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return false;
}
const String json = request->getParam("data", true)->value();
if (json.length() > max_document_size) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return false;
}
const DeserializationError error = deserializeJson(json_document, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
return false;
}
return true;
}
WebApiClass WebApi;

View File

@ -53,38 +53,13 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("delete"))) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;

View File

@ -97,38 +97,13 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > MQTT_JSON_DOC_SIZE) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(MQTT_JSON_DOC_SIZE);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root, MQTT_JSON_DOC_SIZE)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("curPin")
|| root.containsKey("display"))) {
retMsg["message"] = "Values are missing!";

View File

@ -84,38 +84,13 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("serial")
&& root.containsKey("pollinterval")
&& root.containsKey("nrf_palevel")

View File

@ -88,38 +88,13 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("serial")
&& root.containsKey("name"))) {
retMsg["message"] = "Values are missing!";
@ -188,38 +163,13 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("id") && root.containsKey("serial") && root.containsKey("name") && root.containsKey("channel"))) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
@ -333,38 +283,13 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("id"))) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
@ -403,38 +328,13 @@ void WebApiInverterClass::onInverterOrder(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("order"))) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;

View File

@ -58,38 +58,13 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("serial")
&& root.containsKey("limit_value")
&& root.containsKey("limit_type"))) {

View File

@ -23,38 +23,13 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > MQTT_JSON_DOC_SIZE) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(MQTT_JSON_DOC_SIZE);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root, MQTT_JSON_DOC_SIZE)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("reboot"))) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;

View File

@ -99,38 +99,13 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > MQTT_JSON_DOC_SIZE) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(MQTT_JSON_DOC_SIZE);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root, MQTT_JSON_DOC_SIZE)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("mqtt_enabled")
&& root.containsKey("mqtt_hostname")
&& root.containsKey("mqtt_port")

View File

@ -83,38 +83,13 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("ssid")
&& root.containsKey("password")
&& root.containsKey("hostname")

View File

@ -95,38 +95,13 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("ntp_server")
&& root.containsKey("ntp_timezone")
&& root.containsKey("longitude")
@ -219,38 +194,13 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("year")
&& root.containsKey("month")
&& root.containsKey("day")

View File

@ -51,38 +51,13 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!(root.containsKey("serial")
&& (root.containsKey("power")
|| root.containsKey("restart")))) {

View File

@ -42,38 +42,13 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
}
AsyncJsonResponse* response = new AsyncJsonResponse();
auto& retMsg = response->getRoot();
retMsg["type"] = "warning";
if (!request->hasParam("data", true)) {
retMsg["message"] = "No values found!";
retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength();
request->send(response);
return;
}
const String json = request->getParam("data", true)->value();
if (json.length() > 1024) {
retMsg["message"] = "Data too large!";
retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength();
request->send(response);
return;
}
DynamicJsonDocument root(1024);
const DeserializationError error = deserializeJson(root, json);
if (error) {
retMsg["message"] = "Failed to parse data!";
retMsg["code"] = WebApiError::GenericParseError;
response->setLength();
request->send(response);
if (!WebApi.parseRequestData(request, response, root)) {
return;
}
auto& retMsg = response->getRoot();
if (!root.containsKey("password")
&& root.containsKey("allow_readonly")) {
retMsg["message"] = "Values are missing!";