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) {
140 res->status(200).json({{
"status",
"deploy-ack"},
141 {
"reload_mode", reloadResult
.mode},
146 res->status(200).json(
147 {{
"status",
"deploy-ack"}, {
"reload_mode",
"none"}, {
"instances", 0}, {
"subscribed", 0}, {
"unsubscribed", 0}});
149 }
catch (
const std::exception& e) {
150 res->status(500).json({{
"error",
"Deploy failed"}, {
"details", e.what()}});
155 api.post(
"/config/validate", [] APPLICATION(req, res) {
157 const std::string bodyStr(req->body.begin(), req->body.end());
158 auto document =
nlohmann::json::parse(bodyStr);
164 res->status(422).json({{
"valid",
false}, {
"error",
"Validation failed"}});
166 res->status(200).json({{
"valid",
true}});
168 }
catch (
const std::exception& e) {
169 res->status(400).json({{
"error",
"Validation exception"}, {
"details", e.what()}});
174 api.get(
"/config/validateDraft", [configApplication] APPLICATION(req, res) {
178 if (!std::filesystem::exists(draftPath)) {
179 res->status(404).json({{
"valid",
false}, {
"error",
"No draft configuration available"}, {
"path", draftPath}});
183 std::ifstream draftFile(draftPath);
185 res->status(500).json({{
"valid",
false}, {
"error",
"Cannot open draft configuration"}, {
"path", draftPath}});
190 draftFile >> draftDocument;
196 res->status(422).json({{
"valid",
false}, {
"error",
"Draft validation failed"}, {
"path", draftPath}});
198 res->status(200).json({{
"valid",
true}, {
"path", draftPath}});
200 }
catch (
const std::exception& e) {
201 res->status(400).json({{
"valid",
false}, {
"error",
"Draft validation exception"}, {
"details", e.what()}});
206 api.post(
"/config/rollback", [configApplication, onDeploy] APPLICATION(req, res) {
208 const std::string bodyStr(req->body.begin(), req->body.end());
209 auto jsonBody =
nlohmann::json::parse(bodyStr);
211 if (!jsonBody.contains(
"version_id")) {
212 res->status(400).json({{
"error",
"Missing version_id"}});
216 std::string versionId = jsonBody[
"version_id"];
228 reloadResult = onDeploy(mustReconnect);
231 res->status(200).json({{
"status",
"deploy-ack"},
232 {
"reload_mode", reloadResult
.mode},
236 }
catch (
const std::exception& e) {
237 res->status(500).json({{
"error",
"Rollback failed"}, {
"details", e.what()}});
242 api.get(
"/config/history", [configApplication] APPLICATION(req, res) {
246 for (
const auto& h : history) {
249 res->status(200).json(list);
250 }
catch ([[maybe_unused]]
const std::exception& e) {
251 res->status(500).json({{
"error",
"Failed to fetch history"}});
255 api.get(
"/", [] APPLICATION(req, res) {
256 res->redirect(
"/ui");
259 api.get(
"/ui", [] APPLICATION(req, res) {
260 res->redirect(
"/ui/index.html");
264 express::middleware::StaticMiddleware(
"/home/voc/tmp/integrator/mqtt-integrator-ui/dist/mqtt-integrator-ui/browser"));
266 api.get(
"*", [] APPLICATION(req, res) {
267 res->redirect(
"/ui/index.html");