|
|
@ -1,3 +1,5 @@ |
|
|
|
// this file is derived from a boost::beast sample
|
|
|
|
|
|
|
|
#include <boost/beast/core.hpp>
|
|
|
|
#include <boost/beast/http.hpp>
|
|
|
|
#include <boost/beast/version.hpp>
|
|
|
@ -14,11 +16,14 @@ namespace http = beast::http; // from <boost/beast/http.hpp> |
|
|
|
namespace net = boost::asio; // from <boost/asio.hpp>
|
|
|
|
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
|
|
|
|
|
|
|
#include "webserver.hh"
|
|
|
|
|
|
|
|
namespace pEp { |
|
|
|
Webserver::Webserver(net::ip::address addr, unsigned short port, std::string doc_root) |
|
|
|
: _ioc(1), _acceptor(_ioc, {addr, port}), _doc_root(doc_root) { } |
|
|
|
|
|
|
|
// Return a reasonable mime type based on the extension of a file.
|
|
|
|
beast::string_view |
|
|
|
mime_type(beast::string_view path) |
|
|
|
static beast::string_view mime_type(beast::string_view path) |
|
|
|
{ |
|
|
|
using beast::iequals; |
|
|
|
auto const ext = [&path] |
|
|
@ -54,8 +59,7 @@ mime_type(beast::string_view path) |
|
|
|
|
|
|
|
// Append an HTTP rel-path to a local filesystem path.
|
|
|
|
// The returned path is normalized for the platform.
|
|
|
|
std::string |
|
|
|
path_cat( |
|
|
|
static std::string path_cat( |
|
|
|
beast::string_view base, |
|
|
|
beast::string_view path) |
|
|
|
{ |
|
|
@ -86,8 +90,7 @@ path_cat( |
|
|
|
template< |
|
|
|
class Body, class Allocator, |
|
|
|
class Send> |
|
|
|
void |
|
|
|
handle_request( |
|
|
|
void handle_request( |
|
|
|
beast::string_view doc_root, |
|
|
|
http::request<Body, http::basic_fields<Allocator>>&& req, |
|
|
|
Send&& send) |
|
|
@ -229,10 +232,7 @@ struct send_lambda |
|
|
|
}; |
|
|
|
|
|
|
|
// Handles an HTTP server connection
|
|
|
|
void |
|
|
|
do_session( |
|
|
|
tcp::socket& socket, |
|
|
|
std::shared_ptr<std::string const> const& doc_root) |
|
|
|
void Webserver::do_session(tcp::socket& socket) |
|
|
|
{ |
|
|
|
bool close = false; |
|
|
|
beast::error_code ec; |
|
|
@ -254,7 +254,7 @@ do_session( |
|
|
|
return fail(ec, "read"); |
|
|
|
|
|
|
|
// Send the response
|
|
|
|
handle_request(*doc_root, std::move(req), lambda); |
|
|
|
handle_request(_doc_root, std::move(req), lambda); |
|
|
|
if(ec) |
|
|
|
return fail(ec, "write"); |
|
|
|
if(close) |
|
|
@ -271,34 +271,20 @@ do_session( |
|
|
|
// At this point the connection is closed gracefully
|
|
|
|
} |
|
|
|
|
|
|
|
int start_webserver(net::address addr, unsigned short port, string doc_root) |
|
|
|
void Webserver::run() |
|
|
|
{ |
|
|
|
try |
|
|
|
// The acceptor receives incoming connections
|
|
|
|
for(;;) |
|
|
|
{ |
|
|
|
// The io_context is required for all I/O
|
|
|
|
net::io_context ioc{1}; |
|
|
|
// This will receive the new connection
|
|
|
|
tcp::socket socket{_ioc}; |
|
|
|
|
|
|
|
// The acceptor receives incoming connections
|
|
|
|
tcp::acceptor acceptor{ioc, {addr, port}}; |
|
|
|
for(;;) |
|
|
|
{ |
|
|
|
// This will receive the new connection
|
|
|
|
tcp::socket socket{ioc}; |
|
|
|
|
|
|
|
// Block until we get a connection
|
|
|
|
acceptor.accept(socket); |
|
|
|
// Block until we get a connection
|
|
|
|
_acceptor.accept(socket); |
|
|
|
|
|
|
|
// Launch the session, transferring ownership of the socket
|
|
|
|
std::thread{std::bind( |
|
|
|
&do_session, |
|
|
|
std::move(socket), |
|
|
|
doc_root)}.detach(); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (const std::exception& e) |
|
|
|
{ |
|
|
|
std::cerr << "Error: " << e.what() << std::endl; |
|
|
|
return EXIT_FAILURE; |
|
|
|
// Launch the session, transferring ownership of the socket
|
|
|
|
std::function< void() > tf = [&](){do_session(socket);}; |
|
|
|
std::thread{tf}.detach(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|