diff --git a/src/endpoints_handlers/HandleRequest.h b/src/endpoints_handlers/HandleRequest.h index 4d7c0ad..fed5b13 100644 --- a/src/endpoints_handlers/HandleRequest.h +++ b/src/endpoints_handlers/HandleRequest.h @@ -7,101 +7,17 @@ #include "Controller.h" #include "AuthRegistrationExecutor.h" #include "RootExecutor.h" -#include "./../helpers/helpers.h" namespace uad { template void HandleRequest( boost::beast::string_view doc_root, - boost::beast::http::request>&& req, Send&& send) + boost::beast::http::request>&& req, + Send&& send) { - auto const bad_request = [&req](boost::beast::string_view why) - { - boost::beast::http::response 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; - }; + static RootExecutor root_executor; - auto const not_found = [&req](boost::beast::string_view target) - { - boost::beast::http::response 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; - }; - - auto const server_error = [&req](boost::beast::string_view what) - { - boost::beast::http::response 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; - }; - - static RootExecutor root_executor; - - if (req.method() != boost::beast::http::verb::get && - req.method() != boost::beast::http::verb::head) - return send(bad_request("Unknown boost::beast::HTTP-method")); - - if (req.target().empty() || req.target()[0] != '/' || - req.target().find("..") != boost::beast::string_view::npos) - return send(bad_request("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(not_found(req.target())); - - if (ec) - return send(server_error(ec.message())); - - auto const size = body.size(); - - if (req.method() == boost::beast::http::verb::head) - { - boost::beast::http::response 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)); - } - - boost::beast::http::response 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)); + root_executor(doc_root, std::move(req), std::forward(send)); } } diff --git a/src/endpoints_handlers/RootExecutor.h b/src/endpoints_handlers/RootExecutor.h index 593fc53..e7b3be0 100644 --- a/src/endpoints_handlers/RootExecutor.h +++ b/src/endpoints_handlers/RootExecutor.h @@ -2,11 +2,12 @@ #include "IController.h" #include "Controller.h" #include "AuthRegistrationExecutor.h" +#include "./../helpers/helpers.h" namespace uad { -template -class RootExecutor : public IExecutor +template +class RootExecutor { using IRouteExecutor = IExecutor; using RouteAuthRegistrationExecutor = AuthRegistrationExecutor< @@ -14,6 +15,10 @@ class RootExecutor : public IExecutor 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_; @@ -29,37 +34,124 @@ public: ); } - boost::beast::http::response operator ()( - boost::beast::http::request>&& req - ) override + void operator ()( + boost::beast::string_view doc_root, + Request&& req, + Send&& send + ) { - auto const not_found = [&req](boost::beast::string_view target) + const std::string& route = req.target(); + const bool is_match_route = !routes_pathes_.count(route); + + if (is_match_route) { - boost::beast::http::response res{ - boost::beast::http::status::not_found, req.version() + 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, "text/html"); + res.set(boost::beast::http::field::content_type, MimeType(path)); + res.content_length(size); res.keep_alive(req.keep_alive()); - res.body() = "The resource '" + std::string(target) + "' was not found."; - res.prepare_payload(); - return res; - }; + return send(std::move(res)); + } - const std::string& route = req.target(); - const bool is_match_no_route = !routes_pathes_.count(route); + 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)); + } - if (is_match_no_route) return not_found(req.target()); +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; + } - std::optional> maybe_executor_ptr = routes_pathes_ - .at(route) - ->FindExecutor(req.method()); + 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; + } - if (!maybe_executor_ptr.has_value()) return not_found(req.target()); - - IRouteExecutor& executor = *maybe_executor_ptr.value(); - - return executor(std::move(req)); + 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; } }; }