Change codeStyle

This commit is contained in:
Антон 2023-11-04 02:05:40 +03:00
parent 0ff54f68f2
commit 2c8518b092
5 changed files with 63 additions and 33 deletions

View File

@ -26,12 +26,14 @@ struct ContentType
{ {
ContentType() = delete; ContentType() = delete;
constexpr static std::string_view constexpr static std::string_view
TEXT_HTML = "text/html"sv; TEXT_HTML = "text/html"sv;
// При необходимости внутрь ContentType можно добавить и другие типы контента // При необходимости внутрь ContentType можно добавить и другие типы контента
}; };
// Создаёт StringResponse с заданными параметрами // Создаёт StringResponse с заданными параметрами
StringResponse MakeStringResponse(http::status status, std::string_view body, unsigned http_version, StringResponse MakeStringResponse(http::status status,
std::string_view body,
unsigned http_version,
bool keep_alive, bool keep_alive,
std::string_view content_type = ContentType::TEXT_HTML) std::string_view content_type = ContentType::TEXT_HTML)
{ {
@ -46,7 +48,10 @@ StringResponse MakeStringResponse(http::status status, std::string_view body, un
StringResponse HandleRequest(StringRequest&& req) StringResponse HandleRequest(StringRequest&& req)
{ {
// Подставьте сюда код из синхронной версии HTTP-сервера // Подставьте сюда код из синхронной версии HTTP-сервера
return MakeStringResponse(http::status::ok, "OK"sv, req.version(), req.keep_alive()); return MakeStringResponse(http::status::ok,
"OK"sv,
req.version(),
req.keep_alive());
} }
// Запускает функцию fn на n потоках, включая текущий // Запускает функцию fn на n потоках, включая текущий
@ -71,21 +76,24 @@ int main()
const unsigned num_threads = std::thread::hardware_concurrency(); const unsigned num_threads = std::thread::hardware_concurrency();
net::io_context ioc(num_threads); net::io_context ioc(num_threads);
tcp::acceptor acceptor(net::make_strand(ioc)); tcp::acceptor acceptor(net::make_strand(ioc));
// Подписываемся на сигналы и при их получении завершаем работу сервера // Подписываемся на сигналы и при их получении завершаем работу сервера
net::signal_set signals(ioc, SIGINT, SIGTERM); net::signal_set signals(ioc, SIGINT, SIGTERM);
signals.async_wait([&ioc](const sys::error_code& ec, [[maybe_unused]] int signal_number) signals.async_wait([&ioc](const sys::error_code& ec,
[[maybe_unused]] int signal_number)
{ {
if (!ec) if (!ec)
{ {
cout << "Signal "sv << signal_number << " received"sv << endl; cout << "Signal "sv << signal_number << " received"sv
<< endl;
ioc.stop(); ioc.stop();
} }
}); });
const auto address = net::ip::make_address("0.0.0.0"); const auto address = net::ip::make_address("0.0.0.0");
constexpr net::ip::port_type port = 8080; constexpr
net::ip::port_type port = 8080;
http_server::ServeHttp(ioc, {address, port}, [](auto&& req, auto&& sender) http_server::ServeHttp(ioc, {address, port}, [](auto&& req, auto&& sender)
{ {
sender(HandleRequest(std::forward<decltype(req)>(req))); sender(HandleRequest(std::forward<decltype(req)>(req)));

View File

@ -14,10 +14,14 @@
namespace http_server namespace http_server
{ {
template<typename RequestHandler> template<typename RequestHandler>
void ServeHttp(net::io_context& ioc, const tcp::endpoint& endpoint, RequestHandler&& handler) void ServeHttp(net::io_context& ioc,
const tcp::endpoint& endpoint,
RequestHandler&& handler)
{ {
using MyListener = Listener<std::decay_t<RequestHandler>>; using MyListener = Listener<std::decay_t < RequestHandler>>;
std::make_shared<MyListener>(ioc, endpoint, std::forward<RequestHandler>(handler))->Run(); std::make_shared<MyListener>(ioc,
endpoint,
std::forward<RequestHandler>(handler))->Run();
} }
} }

View File

@ -10,22 +10,25 @@
#include "session_base.h" #include "session_base.h"
namespace http_server { namespace http_server
{
namespace net = boost::asio; namespace net = boost::asio;
using tcp = net::ip::tcp; using tcp = net::ip::tcp;
namespace beast = boost::beast; namespace beast = boost::beast;
namespace http = beast::http; namespace http = beast::http;
template <typename RequestHandler> template<typename RequestHandler>
class Session : public SessionBase, public std::enable_shared_from_this<Session<RequestHandler>> { class Session
: public SessionBase,
public std::enable_shared_from_this<Session<RequestHandler>>
{
RequestHandler request_handler_; RequestHandler request_handler_;
public: public:
template<class Handler> template<class Handler>
Session(tcp::socket&& socket, Handler&& request_handler) Session(tcp::socket&& socket, Handler&& request_handler)
: SessionBase(std::move(socket)), request_handler_(request_handler) : SessionBase(std::move(socket)), request_handler_(request_handler) {}
{}
std::shared_ptr<SessionBase> GetSharedThis() override std::shared_ptr<SessionBase> GetSharedThis() override
{ {
@ -33,13 +36,16 @@ class Session : public SessionBase, public std::enable_shared_from_this<Session<
} }
private: private:
void HandleRequest(HttpRequest&& request) override { void HandleRequest(HttpRequest&& request) override
{
// Захватываем умный указатель на текущий объект Session в лямбде, // Захватываем умный указатель на текущий объект Session в лямбде,
// чтобы продлить время жизни сессии до вызова лямбды. // чтобы продлить время жизни сессии до вызова лямбды.
// Используется generic-лямбда функция, способная принять response произвольного типа // Используется generic-лямбда функция, способная принять response произвольного типа
request_handler_(std::move(request), [self = this->shared_from_this()](auto&& response) { request_handler_(std::move(request),
self->Write(std::move(response)); [self = this->shared_from_this()](auto&& response)
}); {
self->Write(std::move(response));
});
} }
}; };
} // namespace http_server } // namespace http_server

View File

@ -27,7 +27,8 @@ void SessionBase::Read()
request_ = {}; request_ = {};
stream_.expires_after(30s); stream_.expires_after(30s);
http::async_read(stream_, buffer_, request_, http::async_read(stream_, buffer_, request_,
beast::bind_front_handler(&SessionBase::OnRead, GetSharedThis())); beast::bind_front_handler(&SessionBase::OnRead,
GetSharedThis()));
} }
void SessionBase::OnRead(beast::error_code ec, size_t bytes_read) void SessionBase::OnRead(beast::error_code ec, size_t bytes_read)
{ {
@ -54,11 +55,13 @@ void SessionBase::OnWrite(bool close,
boost::beast::error_code ec, boost::beast::error_code ec,
std::size_t bytes_written) std::size_t bytes_written)
{ {
if (ec) { if (ec)
{
return ReportError(ec, "write"sv); return ReportError(ec, "write"sv);
} }
if (close) { if (close)
{
// Семантика ответа требует закрыть соединение // Семантика ответа требует закрыть соединение
return Close(); return Close();
} }

View File

@ -11,8 +11,8 @@
#include <boost/beast/core.hpp> #include <boost/beast/core.hpp>
#include <boost/beast/http.hpp> #include <boost/beast/http.hpp>
namespace http_server { namespace http_server
{
namespace net = boost::asio; namespace net = boost::asio;
using tcp = net::ip::tcp; using tcp = net::ip::tcp;
namespace beast = boost::beast; namespace beast = boost::beast;
@ -22,7 +22,8 @@ using namespace std::literals;
void ReportError(beast::error_code ec, std::string_view what); void ReportError(beast::error_code ec, std::string_view what);
class SessionBase { class SessionBase
{
protected: protected:
using HttpRequest = http::request<http::string_body>; using HttpRequest = http::request<http::string_body>;
@ -40,22 +41,28 @@ class SessionBase {
protected: protected:
explicit SessionBase(tcp::socket&& socket); explicit SessionBase(tcp::socket&& socket);
template <typename Body, typename Fields> template<typename Body, typename Fields>
void Write(http::response<Body, Fields>&& response) { void Write(http::response<Body, Fields>&& response)
{
// Запись выполняется асинхронно, поэтому response перемещаем в область кучи // Запись выполняется асинхронно, поэтому response перемещаем в область кучи
auto safe_response = std::make_shared<http::response<Body, Fields>>(std::move(response)); auto safe_response = std::make_shared < http::response
< Body, Fields>>(std::move(response));
auto self = GetSharedThis(); auto self = GetSharedThis();
http::async_write(stream_, *safe_response, http::async_write(stream_, *safe_response,
[safe_response, self](beast::error_code ec, std::size_t bytes_written) { [safe_response, self](beast::error_code ec,
self->OnWrite(safe_response->need_eof(), ec, bytes_written); std::size_t bytes_written)
{
self->OnWrite(safe_response->need_eof(),
ec,
bytes_written);
}); });
} }
private: private:
beast::tcp_stream stream_; beast::tcp_stream stream_;
beast::flat_buffer buffer_; beast::flat_buffer buffer_;
HttpRequest request_; HttpRequest request_;
void OnRead(beast::error_code ec, [[maybe_unused]] size_t bytes_read); void OnRead(beast::error_code ec, [[maybe_unused]] size_t bytes_read);
@ -63,6 +70,8 @@ class SessionBase {
virtual void HandleRequest(HttpRequest&& request) = 0; virtual void HandleRequest(HttpRequest&& request) = 0;
void OnWrite(bool close, beast::error_code ec, [[maybe_unused]] std::size_t bytes_written); void OnWrite(bool close,
beast::error_code ec,
[[maybe_unused]] std::size_t bytes_written);
}; };
} // namespace http_server } // namespace http_server