67 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			67 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef FILESERVER_BOOST_HXX
 | |
| #define FILESERVER_BOOST_HXX
 | |
| 
 | |
| #include <spdlog/spdlog.h>
 | |
| #include <boost/beast/core.hpp>
 | |
| #include <boost/beast/http.hpp>
 | |
| #include <boost/asio/write.hpp>
 | |
| #include <boost/asio/awaitable.hpp>
 | |
| #include <boost/asio/use_awaitable.hpp>
 | |
| #include <boost/asio/experimental/concurrent_channel.hpp>
 | |
| 
 | |
| namespace beast = boost::beast;
 | |
| namespace http = beast::http;
 | |
| namespace net = boost::asio;
 | |
| 
 | |
| using tcp_stream = typename beast::tcp_stream::rebind_executor<net::use_awaitable_t<>::executor_with_default<net::any_io_executor>>::other;
 | |
| using tcp_buffer = beast::flat_static_buffer<65535>;
 | |
| 
 | |
| template<http::status Status, typename BodyType, typename ReqBody>
 | |
| http::response<BodyType> create_response(const http::request<ReqBody> &req) {
 | |
|     http::response<BodyType> res{Status, req.version()};
 | |
|     res.keep_alive(req.keep_alive());
 | |
|     return std::move(res);
 | |
| }
 | |
| 
 | |
| template<typename ReqBody>
 | |
| net::awaitable<void> send_error(tcp_stream &s, const http::request<ReqBody> &req, std::string &&body) {
 | |
|     auto res = create_response<http::status::bad_request, http::string_body, ReqBody>(req);
 | |
|     res.body() = body;
 | |
|     co_await http::async_write(s, res, net::use_awaitable);
 | |
| }
 | |
| 
 | |
| struct err_handler {
 | |
|     std::source_location loc;
 | |
| 
 | |
|     explicit err_handler(std::source_location loc = std::source_location::current()) : loc(loc) {}
 | |
| 
 | |
|     void operator()(const std::exception_ptr& e) const {
 | |
|         if (!e) return;
 | |
|         try {
 | |
|             std::rethrow_exception(e);
 | |
|         } catch (beast::system_error &se) {
 | |
|             log(se.what());
 | |
|         } catch (std::exception &e1) {
 | |
|             log(e1.what());
 | |
|             //std::cerr << "Error in " << loc.file_name() << ":" << loc.line() << " `" << loc.function_name() << "`\n" << e1.what() << "\n";
 | |
|         }
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     static std::shared_ptr<spdlog::logger> logger;
 | |
| 
 | |
|     template<typename MsgType>
 | |
|     void log(MsgType msg) const {
 | |
|         if (!logger)
 | |
|             logger = spdlog::default_logger()->clone("err_handler");
 | |
|         spdlog::source_loc spd_loc;
 | |
|         spd_loc.filename = loc.file_name();
 | |
|         spd_loc.line = (int)loc.line();
 | |
|         spd_loc.funcname = loc.function_name();
 | |
|         spdlog::log(spd_loc, spdlog::level::err, msg);
 | |
|     }
 | |
| };
 | |
| 
 | |
| 
 | |
| #endif //FILESERVER_BOOST_HXX
 |