Change codeStyle
This commit is contained in:
parent
0ff54f68f2
commit
2c8518b092
22
main.cpp
22
main.cpp
@ -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)));
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user