|
|
@@ -145,20 +145,40 @@ static void handle_api_settings(struct mg_connection *c, struct mg_http_message
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- /* Parse JSON body */
|
|
|
- if (!hm->body.buf || hm->body.len == 0) {
|
|
|
+ /* Parse JSON body - try body field first, then fall back to raw message */
|
|
|
+ char body_buf[2048];
|
|
|
+ size_t body_len = 0;
|
|
|
+
|
|
|
+ if (hm->body.buf && hm->body.len > 0) {
|
|
|
+ body_len = (hm->body.len < sizeof(body_buf) - 1) ? hm->body.len : sizeof(body_buf) - 1;
|
|
|
+ memcpy(body_buf, hm->body.buf, body_len);
|
|
|
+ body_buf[body_len] = '\0';
|
|
|
+ } else {
|
|
|
+ /* Fallback: extract body from raw message after headers */
|
|
|
+ /* Find the end of headers (double CRLF) */
|
|
|
+ const char *raw = hm->message.buf;
|
|
|
+ size_t raw_len = hm->message.len;
|
|
|
+ const char *body_start = strstr(raw, "\r\n\r\n");
|
|
|
+ if (body_start) {
|
|
|
+ body_start += 4; /* Skip \r\n\r\n */
|
|
|
+ body_len = raw_len - (body_start - raw);
|
|
|
+ if (body_len > 0 && body_len < sizeof(body_buf)) {
|
|
|
+ memcpy(body_buf, body_start, body_len);
|
|
|
+ body_buf[body_len] = '\0';
|
|
|
+ } else {
|
|
|
+ body_len = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("[WEB] Settings POST body (%zu bytes): %s\n", body_len, body_len > 0 ? body_buf : "(empty)");
|
|
|
+
|
|
|
+ if (body_len == 0) {
|
|
|
mg_http_reply(c, 400, "Content-Type: application/json\r\nAccess-Control-Allow-Origin: *\r\n",
|
|
|
"{\"error\":\"Empty request body\"}");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- char body_buf[2048];
|
|
|
- size_t body_len = (hm->body.len < sizeof(body_buf) - 1) ? hm->body.len : sizeof(body_buf) - 1;
|
|
|
- memcpy(body_buf, hm->body.buf, body_len);
|
|
|
- body_buf[body_len] = '\0';
|
|
|
-
|
|
|
- printf("[WEB] Settings POST body (%zu bytes): %s\n", body_len, body_buf);
|
|
|
-
|
|
|
cJSON *req = cJSON_Parse(body_buf);
|
|
|
if (!req) {
|
|
|
printf("[WEB] Settings JSON parse failed for body: %s\n", body_buf);
|