From 1931551fa8d11878d1d483e96dfba677b852ce47 Mon Sep 17 00:00:00 2001 From: Niklas Jensen Date: Sun, 25 Jan 2026 01:20:12 +0100 Subject: [PATCH] Remake delete for api to protobuf --- esp32/include/communication/webserver.h | 11 +++++++++++ esp32/include/filesystem.h | 2 +- esp32/src/filesystem.cpp | 16 ++++++++++------ esp32/src/main.cpp | 3 +-- platform_shared/api.options | 2 ++ platform_shared/api.proto | 16 +++++++++++++--- 6 files changed, 38 insertions(+), 12 deletions(-) diff --git a/esp32/include/communication/webserver.h b/esp32/include/communication/webserver.h index 97909d8..1c9bbf5 100644 --- a/esp32/include/communication/webserver.h +++ b/esp32/include/communication/webserver.h @@ -17,6 +17,17 @@ using WsFrameHandler = std::function using WsOpenHandler = std::function; using WsCloseHandler = std::function; +// Macro to register a proto endpoint that extracts a specific payload type +// Usage: PROTO_ENDPOINT(server, "/api/files/delete", file_delete_request, FileSystem::handleDelete) +// Handler signature: esp_err_t handleDelete(httpd_req_t* req, const api_FileDeleteRequest& payload) +#define PROTO_ENDPOINT(server_ref, uri, payload_type, handler) \ + (server_ref).onProto(uri, HTTP_POST, [&](httpd_req_t *request, api_Request *protoReq) { \ + if (protoReq->which_payload != api_Request_##payload_type##_tag) { \ + return WebServer::sendError(request, 400, "Invalid request payload"); \ + } \ + return handler(request, protoReq->payload.payload_type); \ + }) + struct HttpRoute { std::string uri; httpd_method_t method; diff --git a/esp32/include/filesystem.h b/esp32/include/filesystem.h index 688ad3f..84f2f7f 100644 --- a/esp32/include/filesystem.h +++ b/esp32/include/filesystem.h @@ -26,7 +26,7 @@ bool editFile(const char *filename, const char *content); esp_err_t getFilesProto(httpd_req_t *request); esp_err_t getFiles(httpd_req_t *request); esp_err_t getConfigFile(httpd_req_t *request); -esp_err_t handleDelete(httpd_req_t *request, JsonVariant &json); +esp_err_t handleDelete(httpd_req_t *request, const api_FileDeleteRequest &req); esp_err_t handleEdit(httpd_req_t *request, JsonVariant &json); esp_err_t mkdir(httpd_req_t *request, JsonVariant &json); diff --git a/esp32/src/filesystem.cpp b/esp32/src/filesystem.cpp index 15a6fdf..96880d6 100644 --- a/esp32/src/filesystem.cpp +++ b/esp32/src/filesystem.cpp @@ -111,13 +111,17 @@ esp_err_t getConfigFile(httpd_req_t *request) { return httpd_resp_send(request, content.c_str(), content.length()); } -esp_err_t handleDelete(httpd_req_t *request, JsonVariant &json) { - if (json.is()) { - const char *filename = json["file"].as(); - ESP_LOGI(TAG, "Deleting file: %s", filename); - return deleteFile(filename) ? WebServer::sendOk(request) : WebServer::sendError(request, 500, "Delete failed"); +esp_err_t handleDelete(httpd_req_t *request, const api_FileDeleteRequest &req) { + ESP_LOGI(TAG, "Deleting file: %s", req.path); + + api_Response res = api_Response_init_zero; + if (deleteFile(req.path)) { + res.status_code = 200; + res.which_payload = api_Response_empty_message_tag; + return WebServer::sendProto(request, 200, res, api_Response_fields); + } else { + return WebServer::sendError(request, 500, "Delete failed"); } - return WebServer::sendError(request, 400, "Invalid request"); } esp_err_t handleEdit(httpd_req_t *request, JsonVariant &json) { diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index 76a774a..0a5eece 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -106,8 +106,7 @@ void setupServer() { // TODO: REMAKE TO PROTO server.on("/api/config/*", HTTP_GET, [](httpd_req_t *request) { return FileSystem::getConfigFile(request); }); server.on("/api/files", HTTP_GET, [&](httpd_req_t *request) { return FileSystem::getFilesProto(request); }); - server.on("/api/files/delete", HTTP_POST, - [&](httpd_req_t *request, JsonVariant &json) { return FileSystem::handleDelete(request, json); }); + PROTO_ENDPOINT(server, "/api/files/delete", file_delete_request, FileSystem::handleDelete); server.on("/api/files/edit", HTTP_POST, [&](httpd_req_t *request, JsonVariant &json) { return FileSystem::handleEdit(request, json); }); server.on("/api/files/mkdir", HTTP_POST, diff --git a/platform_shared/api.options b/platform_shared/api.options index 539ae00..db89104 100644 --- a/platform_shared/api.options +++ b/platform_shared/api.options @@ -11,3 +11,5 @@ api.FileEntry.children type:FT_POINTER api.FileList.entries type:FT_POINTER api.Response.error_message type:FT_POINTER + +api.FileDeleteRequest.path max_size:128 diff --git a/platform_shared/api.proto b/platform_shared/api.proto index 6da5296..5b7a531 100644 --- a/platform_shared/api.proto +++ b/platform_shared/api.proto @@ -2,6 +2,10 @@ syntax = "proto3"; package api; + +// Empty message for endpoints which only needs a status +message EmptyMessage {} + // ============================================================================= // AP (Access Point) Settings - shared data types // ============================================================================= @@ -54,7 +58,7 @@ message Servo { } message ServoSettings { - repeated Servo servos = 1; // max 12 servos + repeated Servo servos = 1; // max 12 servos } message ServoSettingsRequest {} @@ -66,8 +70,8 @@ message ServoSettingsRequest {} message FileEntry { string name = 1; bool is_directory = 2; - uint32 size = 3; // Only for files - repeated FileEntry children = 4; // Only for directories + uint32 size = 3; // Only for files + repeated FileEntry children = 4; // Only for directories } message FileList { @@ -76,6 +80,10 @@ message FileList { message FileListRequest {} +message FileDeleteRequest { + string path = 1; +} + // ============================================================================= // REST API wrappers - used by HTTP endpoints // ============================================================================= @@ -89,6 +97,7 @@ message Request { ServoSettings servo_settings = 20; ServoSettingsRequest servo_settings_request = 21; FileListRequest file_list_request = 30; + FileDeleteRequest file_delete_request = 31; } } @@ -98,6 +107,7 @@ message Response { string error_message = 2; oneof payload { + EmptyMessage empty_message = 5; APSettings ap_settings = 10; APStatus ap_status = 11; ServoSettings servo_settings = 20;