fix: endpoints result

This commit is contained in:
2025-09-23 21:29:18 +02:00
parent a9f56c1279
commit 025ac7b810
9 changed files with 36 additions and 51 deletions

View File

@@ -11,6 +11,7 @@
#include "spore/types/NodeInfo.h" #include "spore/types/NodeInfo.h"
#include "spore/core/TaskManager.h" #include "spore/core/TaskManager.h"
#include "spore/types/ApiTypes.h" #include "spore/types/ApiTypes.h"
#include "spore/util/Logging.h"
class Service; // Forward declaration class Service; // Forward declaration
@@ -19,15 +20,17 @@ public:
ApiServer(NodeContext& ctx, TaskManager& taskMgr, uint16_t port = 80); ApiServer(NodeContext& ctx, TaskManager& taskMgr, uint16_t port = 80);
void begin(); void begin();
void addService(Service& service); void addService(Service& service);
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler);
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler, void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
std::function<void(AsyncWebServerRequest*, const String&, size_t, uint8_t*, size_t, bool)> uploadHandler); const String& serviceName = "unknown");
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
const std::vector<ParamSpec>& params);
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler, void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
std::function<void(AsyncWebServerRequest*, const String&, size_t, uint8_t*, size_t, bool)> uploadHandler, std::function<void(AsyncWebServerRequest*, const String&, size_t, uint8_t*, size_t, bool)> uploadHandler,
const std::vector<ParamSpec>& params); const String& serviceName = "unknown");
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
const std::vector<ParamSpec>& params, const String& serviceName = "unknown");
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
std::function<void(AsyncWebServerRequest*, const String&, size_t, uint8_t*, size_t, bool)> uploadHandler,
const std::vector<ParamSpec>& params, const String& serviceName = "unknown");
// Static file serving // Static file serving
void serveStatic(const String& uri, fs::FS& fs, const String& path, const String& cache_header = ""); void serveStatic(const String& uri, fs::FS& fs, const String& path, const String& cache_header = "");

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "spore/util/JsonSerializable.h" #include "spore/util/JsonSerializable.h"
#include "spore/util/Logging.h"
#include <ArduinoJson.h> #include <ArduinoJson.h>
namespace spore { namespace spore {
@@ -57,6 +58,7 @@ public:
* @param item The serializable item to add * @param item The serializable item to add
*/ */
void addItem(const util::JsonSerializable& item) { void addItem(const util::JsonSerializable& item) {
// Ensure the array exists and get a reference to it
if (!doc[collectionKey].is<JsonArray>()) { if (!doc[collectionKey].is<JsonArray>()) {
doc[collectionKey] = JsonArray(); doc[collectionKey] = JsonArray();
} }
@@ -70,6 +72,7 @@ public:
* @param item The serializable item to add * @param item The serializable item to add
*/ */
void addItem(util::JsonSerializable&& item) { void addItem(util::JsonSerializable&& item) {
// Ensure the array exists and get a reference to it
if (!doc[collectionKey].is<JsonArray>()) { if (!doc[collectionKey].is<JsonArray>()) {
doc[collectionKey] = JsonArray(); doc[collectionKey] = JsonArray();
} }
@@ -84,7 +87,11 @@ public:
*/ */
template<typename Container> template<typename Container>
void addItems(const Container& items) { void addItems(const Container& items) {
JsonArray arr = doc[collectionKey].to<JsonArray>(); // Ensure the array exists and get a reference to it
if (!doc[collectionKey].is<JsonArray>()) {
doc[collectionKey] = JsonArray();
}
JsonArray arr = doc[collectionKey].as<JsonArray>();
for (const auto& item : items) { for (const auto& item : items) {
JsonObject obj = arr.add<JsonObject>(); JsonObject obj = arr.add<JsonObject>();
item.toJson(obj); item.toJson(obj);

View File

@@ -2,6 +2,7 @@
#include "ApiResponse.h" #include "ApiResponse.h"
#include "EndpointInfoSerializable.h" #include "EndpointInfoSerializable.h"
#include "NodeInfo.h" #include "NodeInfo.h"
#include "spore/util/Logging.h"
#include <vector> #include <vector>
namespace spore { namespace spore {

View File

@@ -21,57 +21,31 @@ void ApiServer::registerEndpoint(const String& uri, int method,
const String& serviceName) { const String& serviceName) {
// Add to local endpoints // Add to local endpoints
endpoints.push_back(EndpointInfo{uri, method, params, serviceName, true}); endpoints.push_back(EndpointInfo{uri, method, params, serviceName, true});
// Update cluster if needed
if (ctx.memberList && !ctx.memberList->empty()) {
auto it = ctx.memberList->find(ctx.hostname);
if (it != ctx.memberList->end()) {
it->second.endpoints.push_back(EndpointInfo{uri, method, params, serviceName, true});
}
}
} }
void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler) { void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
// Get current service name if available const String& serviceName) {
String serviceName = "unknown";
if (!services.empty()) {
serviceName = services.back().get().getName();
}
registerEndpoint(uri, method, {}, serviceName); registerEndpoint(uri, method, {}, serviceName);
server.on(uri.c_str(), method, requestHandler); server.on(uri.c_str(), method, requestHandler);
} }
void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler, void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
std::function<void(AsyncWebServerRequest*, const String&, size_t, uint8_t*, size_t, bool)> uploadHandler) { std::function<void(AsyncWebServerRequest*, const String&, size_t, uint8_t*, size_t, bool)> uploadHandler,
// Get current service name if available const String& serviceName) {
String serviceName = "unknown";
if (!services.empty()) {
serviceName = services.back().get().getName();
}
registerEndpoint(uri, method, {}, serviceName); registerEndpoint(uri, method, {}, serviceName);
server.on(uri.c_str(), method, requestHandler, uploadHandler); server.on(uri.c_str(), method, requestHandler, uploadHandler);
} }
// Overloads that also record minimal capability specs // Overloads that also record minimal capability specs
void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler, void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
const std::vector<ParamSpec>& params) { const std::vector<ParamSpec>& params, const String& serviceName) {
// Get current service name if available
String serviceName = "unknown";
if (!services.empty()) {
serviceName = services.back().get().getName();
}
registerEndpoint(uri, method, params, serviceName); registerEndpoint(uri, method, params, serviceName);
server.on(uri.c_str(), method, requestHandler); server.on(uri.c_str(), method, requestHandler);
} }
void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler, void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
std::function<void(AsyncWebServerRequest*, const String&, size_t, uint8_t*, size_t, bool)> uploadHandler, std::function<void(AsyncWebServerRequest*, const String&, size_t, uint8_t*, size_t, bool)> uploadHandler,
const std::vector<ParamSpec>& params) { const std::vector<ParamSpec>& params, const String& serviceName) {
// Get current service name if available
String serviceName = "unknown";
if (!services.empty()) {
serviceName = services.back().get().getName();
}
registerEndpoint(uri, method, params, serviceName); registerEndpoint(uri, method, params, serviceName);
server.on(uri.c_str(), method, requestHandler, uploadHandler); server.on(uri.c_str(), method, requestHandler, uploadHandler);
} }

View File

@@ -9,7 +9,7 @@ ClusterService::ClusterService(NodeContext& ctx) : ctx(ctx) {}
void ClusterService::registerEndpoints(ApiServer& api) { void ClusterService::registerEndpoints(ApiServer& api) {
api.addEndpoint("/api/cluster/members", HTTP_GET, api.addEndpoint("/api/cluster/members", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleMembersRequest(request); }, [this](AsyncWebServerRequest* request) { handleMembersRequest(request); },
std::vector<ParamSpec>{}); std::vector<ParamSpec>{}, "ClusterService");
} }
void ClusterService::handleMembersRequest(AsyncWebServerRequest* request) { void ClusterService::handleMembersRequest(AsyncWebServerRequest* request) {

View File

@@ -12,7 +12,7 @@ MonitoringService::MonitoringService(CpuUsage& cpuUsage)
void MonitoringService::registerEndpoints(ApiServer& api) { void MonitoringService::registerEndpoints(ApiServer& api) {
api.addEndpoint("/api/monitoring/resources", HTTP_GET, api.addEndpoint("/api/monitoring/resources", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleResourcesRequest(request); }, [this](AsyncWebServerRequest* request) { handleResourcesRequest(request); },
std::vector<ParamSpec>{}); std::vector<ParamSpec>{}, "MonitoringService");
} }
MonitoringService::SystemResources MonitoringService::getSystemResources() const { MonitoringService::SystemResources MonitoringService::getSystemResources() const {

View File

@@ -8,16 +8,16 @@ void NetworkService::registerEndpoints(ApiServer& api) {
// WiFi scanning endpoints // WiFi scanning endpoints
api.addEndpoint("/api/network/wifi/scan", HTTP_POST, api.addEndpoint("/api/network/wifi/scan", HTTP_POST,
[this](AsyncWebServerRequest* request) { handleWifiScanRequest(request); }, [this](AsyncWebServerRequest* request) { handleWifiScanRequest(request); },
std::vector<ParamSpec>{}); std::vector<ParamSpec>{}, "NetworkService");
api.addEndpoint("/api/network/wifi/scan", HTTP_GET, api.addEndpoint("/api/network/wifi/scan", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleGetWifiNetworks(request); }, [this](AsyncWebServerRequest* request) { handleGetWifiNetworks(request); },
std::vector<ParamSpec>{}); std::vector<ParamSpec>{}, "NetworkService");
// Network status and configuration endpoints // Network status and configuration endpoints
api.addEndpoint("/api/network/status", HTTP_GET, api.addEndpoint("/api/network/status", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleNetworkStatus(request); }, [this](AsyncWebServerRequest* request) { handleNetworkStatus(request); },
std::vector<ParamSpec>{}); std::vector<ParamSpec>{}, "NetworkService");
api.addEndpoint("/api/network/wifi/config", HTTP_POST, api.addEndpoint("/api/network/wifi/config", HTTP_POST,
[this](AsyncWebServerRequest* request) { handleSetWifiConfig(request); }, [this](AsyncWebServerRequest* request) { handleSetWifiConfig(request); },
@@ -26,7 +26,7 @@ void NetworkService::registerEndpoints(ApiServer& api) {
ParamSpec{String("password"), true, String("body"), String("string"), {}, String("")}, ParamSpec{String("password"), true, String("body"), String("string"), {}, String("")},
ParamSpec{String("connect_timeout_ms"), false, String("body"), String("number"), {}, String("10000")}, ParamSpec{String("connect_timeout_ms"), false, String("body"), String("number"), {}, String("10000")},
ParamSpec{String("retry_delay_ms"), false, String("body"), String("number"), {}, String("500")} ParamSpec{String("retry_delay_ms"), false, String("body"), String("number"), {}, String("500")}
}); }, "NetworkService");
} }
void NetworkService::handleWifiScanRequest(AsyncWebServerRequest* request) { void NetworkService::handleWifiScanRequest(AsyncWebServerRequest* request) {

View File

@@ -13,7 +13,7 @@ void NodeService::registerEndpoints(ApiServer& api) {
// Status endpoint // Status endpoint
api.addEndpoint("/api/node/status", HTTP_GET, api.addEndpoint("/api/node/status", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleStatusRequest(request); }, [this](AsyncWebServerRequest* request) { handleStatusRequest(request); },
std::vector<ParamSpec>{}); std::vector<ParamSpec>{}, "NodeService");
// Update endpoint with file upload // Update endpoint with file upload
api.addEndpoint("/api/node/update", HTTP_POST, api.addEndpoint("/api/node/update", HTTP_POST,
@@ -23,17 +23,17 @@ void NodeService::registerEndpoints(ApiServer& api) {
}, },
std::vector<ParamSpec>{ std::vector<ParamSpec>{
ParamSpec{String("firmware"), true, String("body"), String("file"), {}, String("")} ParamSpec{String("firmware"), true, String("body"), String("file"), {}, String("")}
}); }, "NodeService");
// Restart endpoint // Restart endpoint
api.addEndpoint("/api/node/restart", HTTP_POST, api.addEndpoint("/api/node/restart", HTTP_POST,
[this](AsyncWebServerRequest* request) { handleRestartRequest(request); }, [this](AsyncWebServerRequest* request) { handleRestartRequest(request); },
std::vector<ParamSpec>{}); std::vector<ParamSpec>{}, "NodeService");
// Endpoints endpoint // Endpoints endpoint
api.addEndpoint("/api/node/endpoints", HTTP_GET, api.addEndpoint("/api/node/endpoints", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleEndpointsRequest(request); }, [this](AsyncWebServerRequest* request) { handleEndpointsRequest(request); },
std::vector<ParamSpec>{}); std::vector<ParamSpec>{}, "NodeService");
} }
void NodeService::handleStatusRequest(AsyncWebServerRequest* request) { void NodeService::handleStatusRequest(AsyncWebServerRequest* request) {

View File

@@ -11,7 +11,7 @@ TaskService::TaskService(TaskManager& taskManager) : taskManager(taskManager) {}
void TaskService::registerEndpoints(ApiServer& api) { void TaskService::registerEndpoints(ApiServer& api) {
api.addEndpoint("/api/tasks/status", HTTP_GET, api.addEndpoint("/api/tasks/status", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleStatusRequest(request); }, [this](AsyncWebServerRequest* request) { handleStatusRequest(request); },
std::vector<ParamSpec>{}); std::vector<ParamSpec>{}, "TaskService");
api.addEndpoint("/api/tasks/control", HTTP_POST, api.addEndpoint("/api/tasks/control", HTTP_POST,
[this](AsyncWebServerRequest* request) { handleControlRequest(request); }, [this](AsyncWebServerRequest* request) { handleControlRequest(request); },
@@ -32,7 +32,7 @@ void TaskService::registerEndpoints(ApiServer& api) {
{String("enable"), String("disable"), String("start"), String("stop"), String("status")}, {String("enable"), String("disable"), String("start"), String("stop"), String("status")},
String("") String("")
} }
}); }, "TaskService");
} }
void TaskService::handleStatusRequest(AsyncWebServerRequest* request) { void TaskService::handleStatusRequest(AsyncWebServerRequest* request) {