#include "Web_Server.h" #include "Gallery_WebSocket_Controller.h" #include "Renderive_WebSocket_Controller.h" #include "Web_Performance_Log.h" #include #include #include #include #include #include #include namespace renderive::web { int run_web_server(std::uint16_t port, const std::filesystem::path& asset_root) { const std::filesystem::path gallery_root = asset_root / "webapp_gallery" / "dist"; const std::filesystem::path gallery_index = gallery_root / "index.html"; if (!std::filesystem::is_regular_file(gallery_index)) { std::cerr << "Renderive Gallery assets not found: " << gallery_index << '\n'; return 3; } initialize_web_performance_log(asset_root / "logs"); const auto controller = std::make_shared(); const auto gallery_controller = std::make_shared(); const auto hardware_threads = std::max(2U, std::thread::hardware_concurrency()); std::cout << "Renderive WebSocket backend: ws://127.0.0.1:" << port << "/renderive\n" << "Renderive control gallery: ws://127.0.0.1:" << port << "/renderive/gallery\n" << "Renderive hosted gallery: http://127.0.0.1:" << port << "/\n" << "Renderive performance log: " << web_performance_log_path().string() << "\n" << "HTTP only serves static HTML/CSS/JS; events and pixels stay on WebSocket.\n"; auto& app = drogon::app(); const auto redirect_to_gallery = []( const drogon::HttpRequestPtr&, std::function&& callback) { callback(drogon::HttpResponse::newRedirectionResponse("/")); }; app.registerHandler("/gallery", redirect_to_gallery, {drogon::Get}); app.registerHandler("/gallery/", redirect_to_gallery, {drogon::Get}); app .registerController(controller) .registerController(gallery_controller) .setDocumentRoot(gallery_root.string()) .setHomePage("index.html") .setStaticFileHeaders({{"Cache-Control", "no-store"}}) .addListener("127.0.0.1", port) .setThreadNum(std::min(8U, hardware_threads)) .setIdleConnectionTimeout(90) .run(); return 0; } } // namespace renderive::web