70 api.use(
express::middleware::JsonMiddleware());
74 api.get(
"/schema", [] APPLICATION(req, res) {
79 api.get(
"/config", [configApplication] APPLICATION(req, res) {
82 }
catch (
const std::exception& e) {
83 res->status(500).json({{
"error",
"Failed to load configuration"}, {
"details", e.what()}});
88 api.patch(
"/config", [configApplication] APPLICATION(req, res) {
90 const std::string bodyStr(req->body.begin(), req->body.end());
94 current = current.patch(patchOps);
99 }
catch (
const nlohmann::json::parse_error& e) {
100 res->status(400).json({{
"error",
"Invalid JSON body"}, {
"details", e.what()}});
101 }
catch (
const std::exception& e) {
102 res->status(422).json({{
"error",
"Patch application failed"}, {
"details", e.what()}});
107 api.post(
"/config", [configApplication] APPLICATION(req, res) {
109 const std::string bodyStr(req->body.begin(), req->body.end());
112 if (!replacement.is_object()) {
113 res->status(422).json({{
"error",
"Config replacement must be a JSON object"}});
120 }
catch (
const nlohmann::json::parse_error& e) {
121 res->status(400).json({{
"error",
"Invalid JSON body"}, {
"details", e.what()}});
122 }
catch (
const std::exception& e) {
123 res->status(422).json({{
"error",
"Config replacement failed"}, {
"details", e.what()}});
128 api.post(
"/config/deploy", [configApplication, onDeploy] APPLICATION(req, res) {
132 bool mustReconnect = configApplication
->setMapping(newMappingJson
);
137 reloadResult = onDeploy(mustReconnect);
140 res->status(200).json({{
"status",
"deploy-ack"},
141 {
"reload_mode", reloadResult
.mode},
145 }
catch (
const std::exception& e) {
146 res->status(500).json({{
"error",
"Deploy failed"}, {
"details", e.what()}});
151 api.post(
"/config/validate", [] APPLICATION(req, res) {
153 const std::string bodyStr(req->body.begin(), req->body.end());
154 auto document =
nlohmann::json::parse(bodyStr);
160 res->status(422).json({{
"valid",
false}, {
"error",
"Validation failed"}});
162 res->status(200).json({{
"valid",
true}});
164 }
catch (
const std::exception& e) {
165 res->status(400).json({{
"error",
"Validation exception"}, {
"details", e.what()}});
170 api.get(
"/config/validateDraft", [configApplication] APPLICATION(req, res) {
174 if (!std::filesystem::exists(draftPath)) {
175 res->status(404).json({{
"valid",
false}, {
"error",
"No draft configuration available"}, {
"path", draftPath}});
179 std::ifstream draftFile(draftPath);
181 res->status(500).json({{
"valid",
false}, {
"error",
"Cannot open draft configuration"}, {
"path", draftPath}});
186 draftFile >> draftDocument;
192 res->status(422).json({{
"valid",
false}, {
"error",
"Draft validation failed"}, {
"path", draftPath}});
194 res->status(200).json({{
"valid",
true}, {
"path", draftPath}});
196 }
catch (
const std::exception& e) {
197 res->status(400).json({{
"valid",
false}, {
"error",
"Draft validation exception"}, {
"details", e.what()}});
202 api.post(
"/config/rollback", [configApplication, onDeploy] APPLICATION(req, res) {
204 const std::string bodyStr(req->body.begin(), req->body.end());
205 auto jsonBody =
nlohmann::json::parse(bodyStr);
207 if (!jsonBody.contains(
"version_id")) {
208 res->status(400).json({{
"error",
"Missing version_id"}});
212 std::string versionId = jsonBody[
"version_id"];
216 bool mustReconnect = configApplication
->setMapping(rolledbackMappingJson
);
221 reloadResult = onDeploy(mustReconnect);
224 res->status(200).json({{
"status",
"deploy-ack"},
225 {
"reload_mode", reloadResult
.mode},
229 }
catch (
const std::exception& e) {
230 res->status(500).json({{
"error",
"Rollback failed"}, {
"details", e.what()}});
235 api.get(
"/config/history", [configApplication] APPLICATION(req, res) {
239 for (
const auto& h : history) {
242 res->status(200).json(list);
243 }
catch ([[maybe_unused]]
const std::exception& e) {
244 res->status(500).json({{
"error",
"Failed to fetch history"}});
248 api.get(
"/", [] APPLICATION(req, res) {
249 res->redirect(
"/ui");
252 api.get(
"/ui", [] APPLICATION(req, res) {
253 res->redirect(
"/ui/index.html");
257 express::middleware::StaticMiddleware(
"/home/voc/tmp/integrator/mqtt-integrator-ui/dist/mqtt-integrator-ui/browser"));
259 api.get(
"*", [] APPLICATION(req, res) {
260 res->redirect(
"/ui/index.html");