web_server 初步改

This commit is contained in:
2026-08-21 12:52:27 +08:00
parent d1aa763fcd
commit c41a8ff62d
14 changed files with 792 additions and 421 deletions
+6 -8
View File
@@ -1,9 +1,9 @@
#include "Web_Server.hpp"
#include "Graph_Metadata.hpp" /* 按图请求描述数据。 */
#include "Graph_Session.hpp"
#include "Graph_WebSocket.hpp"
#include "Plot.hpp"
#include <asio/thread_pool.hpp>
#include <drogon/drogon.h>
#include <nlohmann/json.hpp>
#include <algorithm>
#include <functional>
#include <memory>
@@ -16,14 +16,12 @@ drogon::HttpResponsePtr error_response(drogon::HttpStatusCode status, std::strin
int run_web_server(std::uint16_t port, const std::filesystem::path& asset_root) {
const auto hardware_threads = std::max(2U, std::thread::hardware_concurrency());
auto graph_pool = std::make_shared<asio::thread_pool>(std::min(8U, hardware_threads));
auto registry = std::make_shared<Graph_Registry>(graph_pool->get_executor());
auto registry = std::make_shared<Plot_Registry>(graph_pool->get_executor());
auto websocket = std::make_shared<Graph_WebSocket_Controller>(registry);
auto& app = drogon::app();
app.registerHandler("/api/graphs", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) { callback(json_response(graph_catalog_json())); }, {drogon::Get});
app.registerHandler("/api/graphs/{1}/descriptor", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback, std::string graph_id) { if (!find_graph(graph_id)) { callback(error_response(drogon::k404NotFound, "unknown graph")); return; } callback(json_response({{"prop", graph_prop_descriptor_json(graph_id)}, {"state", graph_state_descriptor_json(graph_id)}, {"state_api", "/api/graphs/" + graph_id + "/state"}, {"prop_api", "/api/graphs/" + graph_id + "/prop"}})); }, {drogon::Get});
app.registerHandler("/api/graphs/{1}/state", [registry](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback, std::string graph_id) { auto session = registry->acquire(graph_id); if (!session) { callback(error_response(drogon::k404NotFound, "unknown graph")); return; } auto output = std::make_shared<std::function<void(const drogon::HttpResponsePtr&)>>(std::move(callback)); session->async_state([output](nlohmann::json state) { (*output)(json_response(std::move(state))); }); }, {drogon::Get});
app.registerHandler("/api/graphs/{1}/prop", [registry](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback, std::string graph_id) { auto session = registry->acquire(graph_id); if (!session) { callback(error_response(drogon::k404NotFound, "unknown graph")); return; } auto output = std::make_shared<std::function<void(const drogon::HttpResponsePtr&)>>(std::move(callback)); session->async_prop([output](nlohmann::json prop) { (*output)(json_response(std::move(prop))); }); }, {drogon::Get});
app.registerHandler("/api/graphs/{1}/prop", [registry](const drogon::HttpRequestPtr& request, std::function<void(const drogon::HttpResponsePtr&)>&& callback, std::string graph_id) { auto session = registry->acquire(graph_id); if (!session) { callback(error_response(drogon::k404NotFound, "unknown graph")); return; } nlohmann::json patch; try { patch = nlohmann::json::parse(request->body()); } catch (const nlohmann::json::exception&) { callback(error_response(drogon::k400BadRequest, "invalid JSON patch")); return; } auto output = std::make_shared<std::function<void(const drogon::HttpResponsePtr&)>>(std::move(callback)); session->async_patch_prop(std::move(patch), [output](nlohmann::json result) { (*output)(json_response(std::move(result))); }); }, {drogon::Patch});
app.registerHandler("/plot", [registry](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) { callback(json_response(registry->catalog())); }, {drogon::Get});
app.registerHandler("/plot/{1}/schema", [registry](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback, std::string plot_id) { auto plot = registry->acquire(plot_id); if (!plot) { callback(error_response(drogon::k404NotFound, "unknown plot")); return; } auto output = std::make_shared<std::function<void(const drogon::HttpResponsePtr&)>>(std::move(callback)); plot->async_schema([output](nlohmann::json schema) { (*output)(json_response(std::move(schema))); }); }, {drogon::Get});
app.registerHandler("/plot/{1}/prop/{2}", [registry](const drogon::HttpRequestPtr& request, std::function<void(const drogon::HttpResponsePtr&)>&& callback, std::string plot_id, std::string key) { auto plot = registry->acquire(plot_id); if (!plot) { callback(error_response(drogon::k404NotFound, "unknown plot")); return; } nlohmann::json value; try { value = nlohmann::json::parse(request->body()); } catch (const nlohmann::json::exception&) { callback(error_response(drogon::k400BadRequest, "invalid JSON value")); return; } auto output = std::make_shared<std::function<void(const drogon::HttpResponsePtr&)>>(std::move(callback)); plot->async_write_prop(std::move(key), std::move(value), [output](nlohmann::json result) { (*output)(json_response(std::move(result))); }); }, {drogon::Put});
app.registerController(websocket).setDocumentRoot(asset_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();
graph_pool->stop();
graph_pool->join();