Full C++23 framework tree: runtime, observability, security, data, app, realtime, supervisor, clients, CLI, example plus enterprise tenancy, audit, operability, governance, supplychain. Postgres via docker compose for tests.
94 lines
3.8 KiB
C++
94 lines
3.8 KiB
C++
#include "App.hpp"
|
|
|
|
#include "../fw/Data.hpp"
|
|
#include "../fw/Router.hpp"
|
|
#include "../fw/Validate.hpp"
|
|
|
|
namespace molo::example::app {
|
|
|
|
// Realtime demos answer over plain HTTP in the skeleton: the WebSocket and
|
|
// Socket.IO endpoints describe the upgrade contract and echo posted frames,
|
|
// SSE streams real event text. Gap: real framing, namespaces, rooms, and
|
|
// long-polling fallback in 06-realtime.md plus matching clients.
|
|
|
|
void register_realtime_demo(fw::Router& router, Services& services) {
|
|
fw::WebdavStore* webdav = services.webdav.get();
|
|
|
|
router.get("/streaming/feed", "stream", [](fw::Request req) {
|
|
(void)req;
|
|
return fw::Response(
|
|
fw::StreamingResponse({"chunk-1\n", "chunk-2\n", "chunk-3\n"}));
|
|
});
|
|
router.get("/streaming/passthrough", "passthrough", [](fw::Request req) {
|
|
std::string target = req.query_or("target", "/health");
|
|
return fw::Response(fw::StreamingResponse(
|
|
{"passthrough from " + target + "\n", "{\"status\":\"ok\"}\n"}));
|
|
});
|
|
|
|
router.get("/ws/chat", "ws", [](fw::Request req) {
|
|
std::string upgrade = req.headers.get("Upgrade");
|
|
if (upgrade == "websocket")
|
|
return fw::JsonResponse(
|
|
"{\"upgraded\":false,\"note\":\"skeleton: echo over POST\"}", 200);
|
|
return fw::JsonResponse(
|
|
"{\"protocol\":\"websocket\",\"path\":\"/ws/chat\",\"upgrade\":"
|
|
"\"send Upgrade: websocket\"}",
|
|
200);
|
|
});
|
|
router.post("/ws/chat", "ws-echo", [](fw::Request req) {
|
|
return fw::JsonResponse(
|
|
"{\"echo\":\"" + fw::json_escape(req.body) + "\"}", 200);
|
|
});
|
|
|
|
router.get("/socketio/rooms", "socketio", [](fw::Request req) {
|
|
(void)req;
|
|
return fw::JsonResponse(
|
|
"{\"protocol\":\"socket.io\",\"namespaces\":[\"/\"],\"rooms\":["
|
|
"\"lobby\"],\"fallback\":\"long-polling\"}",
|
|
200);
|
|
});
|
|
router.post("/socketio/rooms", "socketio-emit", [](fw::Request req) {
|
|
auto input = fw::parse_json_object_flat(req.body);
|
|
if (input.empty()) input = fw::parse_form(req.body);
|
|
std::string room = input.count("room") ? input["room"] : "lobby";
|
|
std::string event = input.count("event") ? input["event"] : "message";
|
|
return fw::JsonResponse("{\"emitted\":\"" + fw::json_escape(event) +
|
|
"\",\"room\":\"" + fw::json_escape(room) +
|
|
"\",\"ack\":true}",
|
|
200);
|
|
});
|
|
|
|
router.get("/sse/events", "sse", [](fw::Request req) {
|
|
(void)req;
|
|
return fw::Response(
|
|
fw::SseResponse({"hello", "tick", "goodbye"}));
|
|
});
|
|
|
|
router.any({fw::Method::Propfind}, "/webdav/files/", "webdav-propfind",
|
|
[webdav](fw::Request req) {
|
|
(void)req;
|
|
return fw::Response(207, webdav->propfind_xml("/files/"),
|
|
"application/xml");
|
|
});
|
|
router.any({fw::Method::Get}, "/webdav/files/{name}", "webdav-get",
|
|
[webdav](fw::Request req) -> fw::Response {
|
|
std::string content;
|
|
if (!webdav->get("/files/" + req.param_or("name", ""), content))
|
|
return fw::JsonResponse("{\"error\":\"not found\"}", 404);
|
|
return fw::TextResponse(content, 200);
|
|
});
|
|
router.any({fw::Method::Put}, "/webdav/files/{name}", "webdav-put",
|
|
[webdav](fw::Request req) {
|
|
webdav->put("/files/" + req.param_or("name", ""), req.body);
|
|
return fw::JsonResponse("{\"stored\":true}", 201);
|
|
});
|
|
router.any({fw::Method::Delete}, "/webdav/files/{name}", "webdav-delete",
|
|
[webdav](fw::Request req) {
|
|
if (!webdav->remove("/files/" + req.param_or("name", "")))
|
|
return fw::JsonResponse("{\"error\":\"not found\"}", 404);
|
|
return fw::JsonResponse("{\"deleted\":true}", 200);
|
|
});
|
|
}
|
|
|
|
} // namespace molo::example::app
|