Browse Source

...

master
Volker Birk 2 years ago
parent
commit
1b2bd21bf8
2 changed files with 53 additions and 43 deletions
  1. +39
    -38
      webserver.cc
  2. +14
    -5
      webserver.hh

+ 39
- 38
webserver.cc View File

@ -48,72 +48,73 @@ static beast::string_view mime_type(beast::string_view path)
if(iequals(ext, ".tif")) return "image/tiff";
if(iequals(ext, ".svg")) return "image/svg+xml";
if(iequals(ext, ".svgz")) return "image/svg+xml";
return "application/text";
return "application/octet-stream";
}
// Report a failure
void fail(beast::error_code ec, char const* what)
static void fail(beast::error_code ec, char const* what)
{
std::cerr << what << ": " << ec.message() << "\n";
;}
void Webserver::add_url_handler(std::string url_regex, handler_t handler)
{
std::lock_guard< std::mutex > lock(_mtx);
_urls.emplace(std::pair< std::string, Handling >(url_regex, {boost::regex(url_regex), handler}));
}
// Handles an HTTP server connection
void Webserver::do_session(tcp::socket& socket)
void Webserver::remove_url_handler(std::string url_regex) {
std::lock_guard< std::mutex > lock(_mtx);
_urls.erase(url_regex);
}
Webserver::handler_t Webserver::find_handler(request& r, boost::cmatch& m)
{
bool close = false;
beast::error_code ec;
for (auto it=_urls.begin(); it!=_urls.end(); ++it) {
if (boost::regex_match(r.target().data(), it->second.regex))
return it->second.handler;
}
// This buffer is required to persist across reads
beast::flat_buffer buffer;
return nullptr;
}
// This lambda is used to send messages
// send_lambda<tcp::socket> lambda{socket, close, ec};
void Webserver::do_session(tcp::socket *socket)
{
beast::error_code ec;
beast::flat_buffer buffer;
while (_running)
{
// Read a request
http::request<http::string_body> req;
http::read(socket, buffer, req, ec);
if(ec == http::error::end_of_stream)
break;
if(ec)
return fail(ec, "read");
// Send the response
// handle_request(_doc_root, std::move(req), lambda);
if(ec)
return fail(ec, "write");
if(close)
{
// This means we should close the connection, usually because
// the response indicated the "Connection: close" semantic.
http::read(*socket, buffer, req, ec);
if (ec == http::error::end_of_stream)
break;
}
}
if (ec)
return fail(ec, "reading from stream");
// Send a TCP shutdown
socket.shutdown(tcp::socket::shutdown_send, ec);
}
// At this point the connection is closed gracefully
socket->shutdown(tcp::socket::shutdown_send, ec);
delete socket;
}
void Webserver::run()
{
_running = true;
// The acceptor receives incoming connections
while (_running)
{
// This will receive the new connection
tcp::socket socket{_ioc};
tcp::socket* socket = new tcp::socket{_ioc};
_acceptor.accept(*socket);
// Block until we get a connection
_acceptor.accept(socket);
// Launch the session, transferring ownership of the socket
std::function< void() > tf = [&](){do_session(socket);};
std::thread{tf}.detach();
}
}
void Webserver::shutdown()
{
_running = false;
}
};

+ 14
- 5
webserver.hh View File

@ -1,7 +1,7 @@
#pragma once
#include <string>
#include <vector>
#include <unordered_map>
#include <boost/asio/ip/tcp.hpp>
#include <boost/regex.hpp>
#include <boost/beast/http.hpp>
@ -24,14 +24,20 @@ namespace pEp {
typedef boost::regex url_t;
typedef http::request< http::string_body > request;
typedef http::response< http::string_body > response;
typedef std::function< response(boost::cmatch, request) > handler_t;
typedef std::function< response*(boost::cmatch, request&) > handler_t;
private:
struct Handling {
boost::regex regex;
handler_t handler;
};
net::io_context _ioc;
tcp::acceptor _acceptor;
std::string _doc_root;
std::vector< std::pair< url_t, handler_t > > _urls;
std::unordered_map< std::string, Handling > _urls;
bool _running;
std::mutex _mtx;
public:
Webserver(net::ip::address addr, unsigned short port, std::string doc_root);
@ -39,12 +45,15 @@ namespace pEp {
Webserver& operator=(const Webserver&) = delete;
~Webserver() { }
void add_url_handler(url_t url, handler_t handler);
void add_url_handler(std::string url_regex, handler_t handler);
void remove_url_handler(std::string url_regex);
void run();
void shutdown();
protected:
void do_session(tcp::socket& socket);
handler_t find_handler(request& r, boost::cmatch& m);
void do_session(tcp::socket *socket);
};
};

Loading…
Cancel
Save