cpp_backend/main.cpp

171 lines
4.7 KiB
C++
Raw Normal View History

#include "src/sdk.h"
//
2024-03-20 20:35:24 +01:00
#include <boost/json.hpp>
#include <boost/json/src.hpp>
2024-03-29 15:34:43 +01:00
#include <boost/log/trivial.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/asio/signal_set.hpp>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
2024-03-20 16:40:04 +01:00
#include <fstream>
2024-03-28 16:26:21 +01:00
#include <iostream>
#include "src/http_server.h"
2024-03-28 16:26:21 +01:00
#include "src/Logger.h"
2024-03-23 18:41:09 +01:00
#include "src/routes.h"
2024-03-23 18:13:15 +01:00
#include "src/handlers/GetMapsHandler.h"
2024-03-23 18:41:09 +01:00
#include "src/handlers/GetMapByIdHandler.h"
2024-03-24 14:51:43 +01:00
#include "src/handlers/GetStaticAssetHandler.h"
namespace
{
namespace net = boost::asio;
using namespace std::literals;
namespace sys = boost::system;
2024-03-20 20:35:24 +01:00
namespace json = boost::json;
namespace http = boost::beast::http;
2024-03-29 16:22:19 +01:00
namespace keywords = boost::log::keywords;
2023-09-13 14:57:22 +02:00
using namespace std;
2024-03-23 18:13:15 +01:00
using namespace http_server;
using net::ip::tcp;
// Запрос, тело которого представлено в виде строки
using StringRequest = http::request<http::string_body>;
// Ответ, тело которого представлено в виде строки
using StringResponse = http::response<http::string_body>;
2024-03-25 17:23:48 +01:00
using FileResponse = http::response<http::file_body>;
StringResponse HandleRequest(StringRequest&& req)
{
2024-03-20 16:40:04 +01:00
const auto route = req.target();
2024-01-20 10:46:22 +01:00
2024-03-23 18:41:09 +01:00
if (equal(k_MapsRoute.begin(),
k_MapsRoute.end(),
2024-03-20 16:40:04 +01:00
route.begin(),
route.end()))
2024-03-20 14:55:57 +01:00
{
2024-03-23 18:13:15 +01:00
return GetMapsHandler(req);
2024-03-20 16:40:04 +01:00
}
2024-03-23 18:41:09 +01:00
else if (equal(k_MapsRoute.begin(),
k_MapsRoute.end(),
2024-03-20 16:40:04 +01:00
route.begin(),
2024-03-23 18:41:09 +01:00
route.begin() + k_MapsRoute.size()))
2024-03-20 16:40:04 +01:00
{
2024-03-23 18:41:09 +01:00
return GetMapByIdHandler(req);
2024-03-20 16:40:04 +01:00
}
else
{
StringResponse res(http::status::bad_request, 1);
res.set(http::field::content_type, content_type::k_JSON);
string body = "{\n"
" \"code\": \"badRequest\",\n"
" \"message\": \"Bad request\"\n"
"} "s;
res.body() = body;
res.content_length(body.size());
res.keep_alive(true);
return res;
2024-03-20 14:55:57 +01:00
}
}
2024-03-25 17:23:48 +01:00
FileResponse HandleRequestFile(StringRequest&& req)
{
2024-03-26 06:25:28 +01:00
return GetStaticAssetHandler(req);
2024-03-25 17:23:48 +01:00
}
// Запускает функцию fn на n потоках, включая текущий
template<typename Fn>
void RunWorkers(unsigned n, const Fn& fn)
{
n = std::max(1u, n);
std::vector<std::jthread> workers;
workers.reserve(n - 1);
// Запускаем n-1 рабочих потоков, выполняющих функцию fn
while (--n)
{
workers.emplace_back(fn);
}
fn();
}
} // namespace
int main()
{
2024-03-29 16:22:19 +01:00
boost::log::add_file_log(keywords::file_name = "./public/my_logs.txt",
keywords::format = "[%TimeStamp%]: %Message%");
BOOST_LOG_TRIVIAL(info) << "Server started!"sv;
2024-03-28 16:26:21 +01:00
const unsigned num_threads = std::thread::hardware_concurrency();
net::io_context ioc(num_threads);
2024-02-21 03:57:28 +01:00
tcp::acceptor acceptor(net::make_strand(ioc));
// Подписываемся на сигналы и при их получении завершаем работу сервера
net::signal_set signals(ioc, SIGINT, SIGTERM);
2023-11-04 00:05:40 +01:00
signals.async_wait([&ioc](const sys::error_code& ec,
[[maybe_unused]] int signal_number)
{
if (!ec)
{
2023-11-04 00:05:40 +01:00
cout << "Signal "sv << signal_number << " received"sv
<< endl;
ioc.stop();
}
});
2024-02-21 03:57:28 +01:00
const auto address = net::ip::make_address("0.0.0.0");
constexpr net::ip::port_type port = 8080;
http_server::ServeHttp(ioc, {address, port}, [](auto&& req, auto&& sender)
2024-03-25 17:23:48 +01:00
{
2024-03-26 06:25:28 +01:00
const auto route = req.target();
2024-03-25 17:23:48 +01:00
2024-03-26 06:25:28 +01:00
if (req.target() == "/"sv || find(route.begin(), route.end(), '.') != route.end())
2024-03-27 06:50:50 +01:00
{
auto res = HandleRequestFile(std::forward<decltype(req)>(req));
if (res.result() == http::status::not_found)
{
StringResponse errres(http::status::bad_request, 1);
errres.set(http::field::content_type, content_type::k_JSON);
string body = "{\n"
" \"code\": \"badRequest\",\n"
" \"message\": \"Bad request\"\n"
"} "s;
errres.body() = body;
errres.content_length(body.size());
errres.keep_alive(true);
sender(errres);
}
else
{
sender(res);
}
}
2024-03-26 06:25:28 +01:00
else
sender(HandleRequest(std::forward<decltype(req)>(req)));
});
2023-09-13 14:57:22 +02:00
net::steady_timer t {ioc, 30s};
t.async_wait([](sys::error_code ec)
{
cout << "Timer expired"sv << endl;
});
std::cout << "Server has started..."sv << std::endl;
RunWorkers(num_threads, [&ioc]
{
ioc.run();
});
}