#include "IExecutor.h" #include "IController.h" #include "Controller.h" #include "AuthRegistrationExecutor.h" #include "./../helpers/helpers.h" namespace uad { template class RootExecutor { using IRouteExecutor = IExecutor; using RouteAuthRegistrationExecutor = AuthRegistrationExecutor< Body, Allocator, boost::beast::http::string_body>; using IRouteController = IController; using RouteController = Controller; using RoutesPathes = std::unordered_map>; using Request = boost::beast::http::request>; using StringResponse = boost::beast::http::response; using EmptyResponse = boost::beast::http::response; using FileResponse = boost::beast::http::response; private: RoutesPathes routes_pathes_; public: RootExecutor() { routes_pathes_["/api/v1/Auth/Register"] = std::make_unique( typename RouteController::HTTPMethodsToExecutors{ {boost::beast::http::verb::get, std::make_shared()} } ); } void operator ()( boost::beast::string_view doc_root, Request&& req, Send&& send ) { const std::string& route = req.target(); const bool is_match_route = routes_pathes_.count(route); if (is_match_route) { std::optional> maybe_executor_ptr = routes_pathes_ .at(route) ->FindExecutor(req.method()); if (maybe_executor_ptr.has_value()) { IRouteExecutor& executor = *maybe_executor_ptr.value(); return send(executor(std::move(req))); } } if (req.method() != boost::beast::http::verb::get && req.method() != boost::beast::http::verb::head) return send(SendBadRequest(std::move(req), "Unknown boost::beast::HTTP-method")); if (req.target().empty() || req.target()[0] != '/' || req.target().find("..") != boost::beast::string_view::npos) return send(SendBadRequest(std::move(req), "Illegal request-target")); std::string path = PathCat(doc_root, req.target()); if (req.target().back() == '/') path.append("index.html"); boost::beast::error_code ec; boost::beast::http::file_body::value_type body; body.open(path.c_str(), boost::beast::file_mode::scan, ec); if (ec == boost::beast::errc::no_such_file_or_directory) return send(SendNotFound(std::move(req),req.target())); if (ec) return send(SendServerError(std::move(req), ec.message())); auto const size = body.size(); if (req.method() == boost::beast::http::verb::head) { EmptyResponse res{ boost::beast::http::status::ok, req.version() }; res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING); res.set(boost::beast::http::field::content_type, MimeType(path)); res.content_length(size); res.keep_alive(req.keep_alive()); return send(std::move(res)); } FileResponse res{ std::piecewise_construct, std::make_tuple(std::move(body)), std::make_tuple(boost::beast::http::status::ok, req.version()) }; res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING); res.set(boost::beast::http::field::content_type, MimeType(path)); res.content_length(size); res.keep_alive(req.keep_alive()); return send(std::move(res)); } private: StringResponse SendBadRequest( Request&& req, boost::beast::string_view why ) { StringResponse res{ boost::beast::http::status::bad_request, req.version() }; res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING); res.set(boost::beast::http::field::content_type, "text/html"); res.keep_alive(req.keep_alive()); res.body() = std::string(why); res.prepare_payload(); return res; } StringResponse SendNotFound( Request&& req, boost::beast::string_view target ) { StringResponse res{ boost::beast::http::status::not_found, req.version() }; res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING); res.set(boost::beast::http::field::content_type, "text/html"); res.keep_alive(req.keep_alive()); res.body() = "The resource '" + std::string(target) + "' was not found."; res.prepare_payload(); return res; } StringResponse SendServerError( Request&& req, boost::beast::string_view what ) { StringResponse res{ boost::beast::http::status::internal_server_error, req.version() }; res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING); res.set(boost::beast::http::field::content_type, "text/html"); res.keep_alive(req.keep_alive()); res.body() = "An error occurred: '" + std::string(what) + "'"; res.prepare_payload(); return res; } }; }