#ifndef HttpEndpoint_h #define HttpEndpoint_h #include #include #include "SecurityManager.h" #include "StatefulService.h" #define HTTP_ENDPOINT_ORIGIN_ID "http" #define HTTPS_ENDPOINT_ORIGIN_ID "https" template class HttpEndpoint { protected: JsonStateReader _stateReader; JsonStateUpdater _stateUpdater; StatefulService * _statefulService; public: HttpEndpoint(JsonStateReader stateReader, JsonStateUpdater stateUpdater, StatefulService * statefulService, AsyncWebServer * server, const String & servicePath, SecurityManager * securityManager, AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN) : _stateReader(stateReader) , _stateUpdater(stateUpdater) , _statefulService(statefulService) { // Create handler for both GET and POST endpoints server->on(servicePath.c_str(), securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { handleRequest(request, json); }, authenticationPredicate)); } protected: // for POST void handleRequest(AsyncWebServerRequest * request, JsonVariant json) { if (request->method() == HTTP_POST) { // Handle POST if (!json.is()) { request->send(400); return; } StateUpdateResult outcome = _statefulService->updateWithoutPropagation(json.as(), _stateUpdater); if (outcome == StateUpdateResult::ERROR) { request->send(400); // error return; } else if (outcome == StateUpdateResult::CHANGED || outcome == StateUpdateResult::CHANGED_RESTART) { // persist changes request->onDisconnect([this] { _statefulService->callUpdateHandlers(); }); if (outcome == StateUpdateResult::CHANGED_RESTART) { request->send(205); // reboot required return; } } } auto * response = new AsyncJsonResponse(false); JsonObject jsonObject = response->getRoot().to(); _statefulService->read(jsonObject, _stateReader); response->setLength(); request->send(response); } }; #endif