generated from Sithas/conan_template
Рефакторинг HandleRequest: вынос целиком в RootExecutor.h, замена длиннах имен алиасами
This commit is contained in:
@@ -7,101 +7,17 @@
|
|||||||
#include "Controller.h"
|
#include "Controller.h"
|
||||||
#include "AuthRegistrationExecutor.h"
|
#include "AuthRegistrationExecutor.h"
|
||||||
#include "RootExecutor.h"
|
#include "RootExecutor.h"
|
||||||
#include "./../helpers/helpers.h"
|
|
||||||
|
|
||||||
namespace uad
|
namespace uad
|
||||||
{
|
{
|
||||||
template <class Body, class Allocator, class Send>
|
template <class Body, class Allocator, class Send>
|
||||||
void HandleRequest(
|
void HandleRequest(
|
||||||
boost::beast::string_view doc_root,
|
boost::beast::string_view doc_root,
|
||||||
boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator>>&& req, Send&& send)
|
boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator>>&& req,
|
||||||
|
Send&& send)
|
||||||
{
|
{
|
||||||
auto const bad_request = [&req](boost::beast::string_view why)
|
static RootExecutor<Body, Allocator, boost::beast::http::string_body, Send> root_executor;
|
||||||
{
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body> 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto const not_found = [&req](boost::beast::string_view target)
|
root_executor(doc_root, std::move(req), std::forward<Send>(send));
|
||||||
{
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body> 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<boost::beast::http::string_body> 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<Body, Allocator, boost::beast::http::string_body> 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<boost::beast::http::empty_body> 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<boost::beast::http::file_body> 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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
#include "IController.h"
|
#include "IController.h"
|
||||||
#include "Controller.h"
|
#include "Controller.h"
|
||||||
#include "AuthRegistrationExecutor.h"
|
#include "AuthRegistrationExecutor.h"
|
||||||
|
#include "./../helpers/helpers.h"
|
||||||
|
|
||||||
namespace uad
|
namespace uad
|
||||||
{
|
{
|
||||||
template <class Body, class Allocator, class ResponseType>
|
template <class Body, class Allocator, class ResponseType, class Send>
|
||||||
class RootExecutor : public IExecutor<Body, Allocator, ResponseType>
|
class RootExecutor
|
||||||
{
|
{
|
||||||
using IRouteExecutor = IExecutor<Body, Allocator, boost::beast::http::string_body>;
|
using IRouteExecutor = IExecutor<Body, Allocator, boost::beast::http::string_body>;
|
||||||
using RouteAuthRegistrationExecutor = AuthRegistrationExecutor<
|
using RouteAuthRegistrationExecutor = AuthRegistrationExecutor<
|
||||||
@@ -14,6 +15,10 @@ class RootExecutor : public IExecutor<Body, Allocator, ResponseType>
|
|||||||
using IRouteController = IController<Body, Allocator, boost::beast::http::string_body>;
|
using IRouteController = IController<Body, Allocator, boost::beast::http::string_body>;
|
||||||
using RouteController = Controller<Body, Allocator, boost::beast::http::string_body>;
|
using RouteController = Controller<Body, Allocator, boost::beast::http::string_body>;
|
||||||
using RoutesPathes = std::unordered_map<std::string, std::unique_ptr<IRouteController>>;
|
using RoutesPathes = std::unordered_map<std::string, std::unique_ptr<IRouteController>>;
|
||||||
|
using Request = boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator>>;
|
||||||
|
using StringResponse = boost::beast::http::response<boost::beast::http::string_body>;
|
||||||
|
using EmptyResponse = boost::beast::http::response<boost::beast::http::empty_body>;
|
||||||
|
using FileResponse = boost::beast::http::response<boost::beast::http::file_body>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RoutesPathes routes_pathes_;
|
RoutesPathes routes_pathes_;
|
||||||
@@ -29,13 +34,100 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::beast::http::response<ResponseType> operator ()(
|
void operator ()(
|
||||||
boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator>>&& req
|
boost::beast::string_view doc_root,
|
||||||
) override
|
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<boost::beast::http::string_body> res{
|
std::optional<std::shared_ptr<IRouteExecutor>> 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()
|
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::server, BOOST_BEAST_VERSION_STRING);
|
||||||
@@ -44,22 +136,22 @@ public:
|
|||||||
res.body() = "The resource '" + std::string(target) + "' was not found.";
|
res.body() = "The resource '" + std::string(target) + "' was not found.";
|
||||||
res.prepare_payload();
|
res.prepare_payload();
|
||||||
return res;
|
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);
|
||||||
const std::string& route = req.target();
|
res.set(boost::beast::http::field::content_type, "text/html");
|
||||||
const bool is_match_no_route = !routes_pathes_.count(route);
|
res.keep_alive(req.keep_alive());
|
||||||
|
res.body() = "An error occurred: '" + std::string(what) + "'";
|
||||||
if (is_match_no_route) return not_found(req.target());
|
res.prepare_payload();
|
||||||
|
return res;
|
||||||
std::optional<std::shared_ptr<IRouteExecutor>> maybe_executor_ptr = routes_pathes_
|
|
||||||
.at(route)
|
|
||||||
->FindExecutor(req.method());
|
|
||||||
|
|
||||||
if (!maybe_executor_ptr.has_value()) return not_found(req.target());
|
|
||||||
|
|
||||||
IRouteExecutor& executor = *maybe_executor_ptr.value();
|
|
||||||
|
|
||||||
return executor(std::move(req));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user