refactor: simplify endpoint and capabilities

This commit is contained in:
2025-09-13 19:15:07 +02:00
parent 12caeb0be6
commit 72b559e047
18 changed files with 1055 additions and 40 deletions

View File

@@ -15,40 +15,63 @@ const char* ApiServer::methodToStr(int method) {
ApiServer::ApiServer(NodeContext& ctx, TaskManager& taskMgr, uint16_t port) : server(port), ctx(ctx), taskManager(taskMgr) {}
void ApiServer::registerServiceForLocalNode(const String& uri, int method) {
serviceRegistry.push_back(std::make_tuple(uri, method));
void ApiServer::registerEndpoint(const String& uri, int method,
const std::vector<ParamSpec>& params,
const String& serviceName) {
// Add to local endpoints
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.apiEndpoints.push_back(std::make_tuple(uri, method));
it->second.endpoints.push_back(EndpointInfo{uri, method, params, serviceName, true});
}
}
}
void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler) {
registerServiceForLocalNode(uri, method);
// Get current service name if available
String serviceName = "unknown";
if (!services.empty()) {
serviceName = services.back().get().getName();
}
registerEndpoint(uri, method, {}, serviceName);
server.on(uri.c_str(), method, 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) {
registerServiceForLocalNode(uri, method);
// Get current service name if available
String serviceName = "unknown";
if (!services.empty()) {
serviceName = services.back().get().getName();
}
registerEndpoint(uri, method, {}, serviceName);
server.on(uri.c_str(), method, requestHandler, uploadHandler);
}
// Overloads that also record minimal capability specs
void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
const std::vector<ParamSpec>& params) {
ctx.capabilities.push_back(EndpointCapability{uri, method, params});
registerServiceForLocalNode(uri, method);
// Get current service name if available
String serviceName = "unknown";
if (!services.empty()) {
serviceName = services.back().get().getName();
}
registerEndpoint(uri, method, params, serviceName);
server.on(uri.c_str(), method, 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,
const std::vector<ParamSpec>& params) {
ctx.capabilities.push_back(EndpointCapability{uri, method, params});
registerServiceForLocalNode(uri, method);
// Get current service name if available
String serviceName = "unknown";
if (!services.empty()) {
serviceName = services.back().get().getName();
}
registerEndpoint(uri, method, params, serviceName);
server.on(uri.c_str(), method, requestHandler, uploadHandler);
}

View File

@@ -109,13 +109,19 @@ void ClusterManager::fetchNodeInfo(const IPAddress& ip) {
node.status = NodeInfo::ACTIVE;
node.latency = requestDuration;
node.lastSeen = millis();
node.apiEndpoints.clear();
node.endpoints.clear();
if (doc["api"].is<JsonArray>()) {
JsonArray apiArr = doc["api"].as<JsonArray>();
for (JsonObject apiObj : apiArr) {
String uri = (const char*)apiObj["uri"];
int method = apiObj["method"];
node.apiEndpoints.push_back(std::make_tuple(uri, method));
// Create basic EndpointInfo without params for cluster nodes
EndpointInfo endpoint;
endpoint.uri = uri;
endpoint.method = method;
endpoint.isLocal = false;
endpoint.serviceName = "remote";
node.endpoints.push_back(endpoint);
}
}
// Parse labels if present

View File

@@ -1,7 +1,7 @@
#include "services/NodeService.h"
#include "ApiServer.h"
NodeService::NodeService(NodeContext& ctx) : ctx(ctx) {}
NodeService::NodeService(NodeContext& ctx, ApiServer& apiServer) : ctx(ctx), apiServer(apiServer) {}
void NodeService::registerEndpoints(ApiServer& api) {
// Status endpoint
@@ -24,9 +24,9 @@ void NodeService::registerEndpoints(ApiServer& api) {
[this](AsyncWebServerRequest* request) { handleRestartRequest(request); },
std::vector<ParamSpec>{});
// Capabilities endpoint
api.addEndpoint("/api/node/capabilities", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleCapabilitiesRequest(request); },
// Endpoints endpoint
api.addEndpoint("/api/node/endpoints", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleEndpointsRequest(request); },
std::vector<ParamSpec>{});
}
@@ -121,18 +121,18 @@ void NodeService::handleRestartRequest(AsyncWebServerRequest* request) {
});
}
void NodeService::handleCapabilitiesRequest(AsyncWebServerRequest* request) {
void NodeService::handleEndpointsRequest(AsyncWebServerRequest* request) {
JsonDocument doc;
JsonArray endpointsArr = doc["endpoints"].to<JsonArray>();
// Add all registered capabilities
for (const auto& cap : ctx.capabilities) {
// Add all registered endpoints from ApiServer
for (const auto& endpoint : apiServer.getEndpoints()) {
JsonObject obj = endpointsArr.add<JsonObject>();
obj["uri"] = cap.uri;
obj["method"] = ApiServer::methodToStr(cap.method);
if (!cap.params.empty()) {
obj["uri"] = endpoint.uri;
obj["method"] = ApiServer::methodToStr(endpoint.method);
if (!endpoint.params.empty()) {
JsonArray paramsArr = obj["params"].to<JsonArray>();
for (const auto& ps : cap.params) {
for (const auto& ps : endpoint.params) {
JsonObject p = paramsArr.add<JsonObject>();
p["name"] = ps.name;
p["location"] = ps.location;