#include #include #include #include void Application::web_server_started(std::size_t port) { std::cout << "Web server started and listening on " << port << ".\n"; }; void Application::secure_web_server_started(std::size_t port) { std::cout << "Secure web server started and listening on " << port << ".\n"; }; Application::Application(const nlohmann::json &cfg) { convert::from_json(cfg.value("http", json::object()), http_server.config); if (cfg.contains("https")) { const auto https = cfg["https"]; if (https.contains("cert") && https.contains("key")) { https_server = std::make_shared(https["cert"], https["key"]); } } if (https_server) { convert::from_json(cfg.value("https", json::object()), https_server->config); } } int Application::run() { std::vector servers; orders orders(data_directory); for (const auto &m : {"GET", "POST", "PUT", "PATCH", "OPTIONS", "HEAD"}) { if (https_server) { https_server->default_resource[m] = [](std::shared_ptr response, ...) { return response::not_found(response); }; } http_server.default_resource[m] = [](std::shared_ptr response, ...) { return response::not_found(response); }; } if (https_server) { servers.emplace_back( [&]() { https_server->start(secure_web_server_started); }); } http_server.resource["^/orders/?$"]["GET"] = [&](std::shared_ptr response, ...) { response->write(Status::success_ok, orders.dump(), {header_access_control, header_application_data}); }; http_server.resource["^/orders/?$"]["PUT"] = [&](std::shared_ptr response, std::shared_ptr request) { const auto content_type = request->header.find("Content-Type"); const auto missing_content_type = content_type == request->header.end(); if (missing_content_type) { return response::not_found(response); } const auto is_json = content_type->second == "application/json"; if (!is_json) { return response::not_found(response); } json data = nullptr; try { request->content >> data; } catch (...) { return response::not_found(response); } if (!data.is_object()) { return response::not_found(response); } data_validator v; if (v.validate(data)) { return response::bad_request(response, v.errors()); } orders.push_back(data); orders.write(); response->write(Status::success_created, data.dump(), {header_access_control, header_application_data}); }; servers.emplace_back([&]() { http_server.start(web_server_started); }); for (auto &server : servers) { server.join(); } return 0; } Application &Application::get(const json &config) { static Application app(config); return app; }