support for device in json body

This commit is contained in:
proddy
2021-08-07 21:46:09 +02:00
parent 38498a5587
commit 088cb7fe40

View File

@@ -33,19 +33,21 @@ WebAPIService::WebAPIService(AsyncWebServer * server, SecurityManager * security
// GET /{device} // GET /{device}
// GET /{device}/{name} // GET /{device}/{name}
// GET /device={device}?cmd={name}?data={value}[?id={hc} // GET /device={device}?cmd={name}?data={value}[?id={hc}]
void WebAPIService::webAPIService_get(AsyncWebServerRequest * request) { void WebAPIService::webAPIService_get(AsyncWebServerRequest * request) {
std::string device(""); // initialize parameters. These will be extracted from the URL
std::string cmd(""); std::string device_s("");
std::string cmd_s("");
std::string value_s("");
int id = -1; int id = -1;
std::string value("");
parse(request, device, cmd, id, value); // pass it defaults parse(request, device_s, cmd_s, id, value_s);
} }
// For POSTS with an optional JSON body // For POSTS with an optional JSON body
// HTTP_POST | HTTP_PUT | HTTP_PATCH // HTTP_POST | HTTP_PUT | HTTP_PATCH
// POST/PUT /{device}[/{hc}][/{name}] // POST /{device}[/{hc|id}][/{name}]
// the body must have 'value'. Optional are device, name, hc and id
void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVariant & json) { void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVariant & json) {
// if no body then treat it as a secure GET // if no body then treat it as a secure GET
if (not json.is<JsonObject>()) { if (not json.is<JsonObject>()) {
@@ -53,13 +55,34 @@ void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVari
return; return;
} }
// extract values from the json // extract values from the json. these will be used as default values
// these will be used as default values
auto && body = json.as<JsonObject>(); auto && body = json.as<JsonObject>();
std::string device = body["name"].as<std::string>(); // note this was called device in the v2 #if defined(EMSESP_STANDALONE)
std::string cmd = body["cmd"].as<std::string>(); Serial.println("webAPIService_post: ");
int id = -1; serializeJson(body, Serial);
Serial.println();
#endif
// make sure we have a value. There must always be a value
if (!body.containsKey(F_(value))) {
send_message_response(request, 400, "Problems parsing JSON, missing value"); // Bad Request
return;
}
std::string value_s = body["value"].as<std::string>(); // always convert value to string
std::string device_s = body["device"].as<std::string>();
// get the command. It can be either 'name' or 'cmd'
std::string cmd_s("");
if (body.containsKey("name")) {
cmd_s = body["name"].as<std::string>();
} else if (body.containsKey("cmd")) {
cmd_s = body["cmd"].as<std::string>();
}
// for id, it can be part of the hc or id keys in the json body
int id = -1;
if (body.containsKey("id")) { if (body.containsKey("id")) {
id = body["id"]; id = body["id"];
} else if (body.containsKey("hc")) { } else if (body.containsKey("hc")) {
@@ -68,15 +91,8 @@ void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVari
id = -1; id = -1;
} }
// make sure we have a value. There must always be a value
if (!body.containsKey(F_(value))) {
send_message_response(request, 400, "Problems parsing JSON"); // Bad Request
return;
}
std::string value = body["value"].as<std::string>(); // always convert value to string
// now parse the URL. The URL is always leading and will overwrite anything provided in the json body // now parse the URL. The URL is always leading and will overwrite anything provided in the json body
parse(request, device, cmd, id, value); // pass it defaults parse(request, device_s, cmd_s, id, value_s); // pass it defaults
} }
// parse the URL looking for query or path parameters // parse the URL looking for query or path parameters
@@ -97,7 +113,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, std::string & device_
uint8_t device_type; uint8_t device_type;
int8_t id_n = -1; // default hc int8_t id_n = -1; // default hc
// check for query parameters first // check for query parameters first, the old style from v2
// /device={device}?cmd={name}?data={value}[?id={hc} // /device={device}?cmd={name}?data={value}[?id={hc}
if (p.paths().size() == 0) { if (p.paths().size() == 0) {
// get the device // get the device
@@ -126,27 +142,31 @@ void WebAPIService::parse(AsyncWebServerRequest * request, std::string & device_
id_n = Helpers::atoint(request->getParam("hc")->value().c_str()); id_n = Helpers::atoint(request->getParam("hc")->value().c_str());
} }
} else { } else {
// parse paths and json data from the OpenAPI standard // parse paths and json data from the newer OpenAPI standard
// /{device}[/{hc}][/{name}] // [/{device}][/{hc}][/{name}]
// first param must be a valid device, which includes "system" // all paths are optional. If not set then take the values from the json body (if available)
device_s = p.paths().front();
auto num_paths = p.paths().size(); // see if we have a device in the path
if (num_paths == 1) { size_t num_paths = p.paths().size();
// if there are no more paths parameters, default to 'info' if (num_paths) {
// cmd_s = "info_short"; // assume the next path is the 'device'. Note this could also have the value of system.
// check empty command in Command::find_command and set the default there! device_s = p.paths().front();
} else if (num_paths == 2) {
cmd_s = p.paths()[1]; if (num_paths == 2) {
} else if (num_paths > 2) { // next path is the name or cmd
// check in Command::find_command makes prefix to TAG cmd_s = p.paths()[1];
cmd_s = p.paths()[1] + "/" + p.paths()[2]; } else if (num_paths > 2) {
// check in Command::find_command makes prefix to TAG
cmd_s = p.paths()[1] + "/" + p.paths()[2];
}
} }
} }
// now go and validate everything
// now go and verify the values
// device check // device check
if (device_s.empty()) { if (device_s.empty()) {
// see if we have a device embedded in the json body, then use that
send_message_response(request, 422, "Missing device"); // Unprocessable Entity send_message_response(request, 422, "Missing device"); // Unprocessable Entity
return; return;
} }
@@ -231,6 +251,8 @@ void WebAPIService::send_message_response(AsyncWebServerRequest * request, uint1
response->setContentType("application/json"); response->setContentType("application/json");
request->send(response); request->send(response);
} }
EMSESP::logger().debug(F("API returns, code: %d, message: %s"), error_code, error_message);
} }
/** /**