mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 21:34:46 +02:00
Documentation work
This commit is contained in:
@@ -39,8 +39,6 @@ A port handler takes the stream object resulting form an incoming connection
|
|||||||
request and constructs a handler-specific connection object which provides
|
request and constructs a handler-specific connection object which provides
|
||||||
the desired behavior.
|
the desired behavior.
|
||||||
|
|
||||||
## Service
|
|
||||||
|
|
||||||
The HTTP ports which come with the example have a system built in which allows
|
The HTTP ports which come with the example have a system built in which allows
|
||||||
installation of framework and user-defined "HTTP services". These services
|
installation of framework and user-defined "HTTP services". These services
|
||||||
inform connections using the port on how to handle specific requests. This is
|
inform connections using the port on how to handle specific requests. This is
|
||||||
@@ -66,3 +64,74 @@ the HTTP ports:
|
|||||||
<img width="880" height = "344" alt = "ServerFramework"
|
<img width="880" height = "344" alt = "ServerFramework"
|
||||||
src="https://raw.githubusercontent.com/vinniefalco/Beast/server/doc/images/server.png">
|
src="https://raw.githubusercontent.com/vinniefalco/Beast/server/doc/images/server.png">
|
||||||
|
|
||||||
|
## PortHandler Requirements
|
||||||
|
```C++
|
||||||
|
/** An synchronous WebSocket @b PortHandler which implements echo.
|
||||||
|
|
||||||
|
This is a port handler which accepts WebSocket upgrade HTTP
|
||||||
|
requests and implements the echo protocol. All received
|
||||||
|
WebSocket messages will be echoed back to the remote host.
|
||||||
|
*/
|
||||||
|
struct PortHandler
|
||||||
|
{
|
||||||
|
/** Accept a TCP/IP socket.
|
||||||
|
|
||||||
|
This function is called when the server has accepted an
|
||||||
|
incoming connection.
|
||||||
|
|
||||||
|
@param sock The connected socket.
|
||||||
|
|
||||||
|
@param ep The endpoint of the remote host.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
on_accept(
|
||||||
|
socket_type&& sock,
|
||||||
|
endpoint_type ep);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Service Requirements
|
||||||
|
|
||||||
|
```C++
|
||||||
|
struct Service
|
||||||
|
{
|
||||||
|
/** Initialize the service
|
||||||
|
|
||||||
|
@param ec Set to the error, if any occurred
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
init(error_code& ec);
|
||||||
|
|
||||||
|
/** Maybe respond to an HTTP request
|
||||||
|
|
||||||
|
Upon handling the response, the service may optionally
|
||||||
|
take ownership of either the stream, the request, or both.
|
||||||
|
|
||||||
|
@param stream The stream representing the connection
|
||||||
|
|
||||||
|
@param ep The remote endpoint of the stream
|
||||||
|
|
||||||
|
@param req The HTTP request
|
||||||
|
|
||||||
|
@param send A function object which operates on a single
|
||||||
|
argument of type beast::http::message. The function object
|
||||||
|
has this equivalent signature:
|
||||||
|
@code
|
||||||
|
template<class Body, class Fields>
|
||||||
|
void send(beast::http::response<Body, Fields>&& res);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@return `true` if the service handled the response.
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
class Stream,
|
||||||
|
class Body, class Fields,
|
||||||
|
class Send>
|
||||||
|
bool
|
||||||
|
respond(
|
||||||
|
Stream&& stream,
|
||||||
|
endpoint_type const& ep,
|
||||||
|
beast::http::request<Body, Fields>&& req,
|
||||||
|
Send const& send) const
|
||||||
|
};
|
||||||
|
```
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
namespace framework {
|
namespace framework {
|
||||||
|
|
||||||
// Base class for a type-erased, queued asynchronous HTTP write
|
// Base class for a type-erased, queued asynchronous HTTP write operation
|
||||||
//
|
//
|
||||||
struct queued_http_write
|
struct queued_http_write
|
||||||
{
|
{
|
||||||
@@ -111,7 +111,7 @@ make_queued_http_write(
|
|||||||
asynchronous calls.
|
asynchronous calls.
|
||||||
|
|
||||||
It uses the Curiously Recurring Template pattern (CRTP) where
|
It uses the Curiously Recurring Template pattern (CRTP) where
|
||||||
we refer to the derivd class in order to access the stream object
|
we refer to the derived class in order to access the stream object
|
||||||
to use for reading and writing. This lets the same class be used
|
to use for reading and writing. This lets the same class be used
|
||||||
for plain and SSL stream objects.
|
for plain and SSL stream objects.
|
||||||
|
|
||||||
@@ -492,7 +492,12 @@ class http_async_port
|
|||||||
service_list<Services...> services_;
|
service_list<Services...> services_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
/** Constructor
|
||||||
|
|
||||||
|
@param instance The server instance which owns this port
|
||||||
|
|
||||||
|
@param log The stream to use for logging
|
||||||
|
*/
|
||||||
http_async_port(
|
http_async_port(
|
||||||
server& instance,
|
server& instance,
|
||||||
std::ostream& log)
|
std::ostream& log)
|
||||||
|
@@ -35,7 +35,7 @@ namespace framework {
|
|||||||
synchronous calls.
|
synchronous calls.
|
||||||
|
|
||||||
It uses the Curiously Recurring Template pattern (CRTP) where
|
It uses the Curiously Recurring Template pattern (CRTP) where
|
||||||
we refer to the derivd class in order to access the stream object
|
we refer to the derived class in order to access the stream object
|
||||||
to use for reading and writing. This lets the same class be used
|
to use for reading and writing. This lets the same class be used
|
||||||
for plain and SSL stream objects.
|
for plain and SSL stream objects.
|
||||||
|
|
||||||
@@ -45,6 +45,7 @@ template<class Derived, class... Services>
|
|||||||
class sync_http_con
|
class sync_http_con
|
||||||
: public http_base
|
: public http_base
|
||||||
{
|
{
|
||||||
|
// This function lets us access members of the derived class
|
||||||
Derived&
|
Derived&
|
||||||
impl()
|
impl()
|
||||||
{
|
{
|
||||||
@@ -271,6 +272,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the stream.
|
// Returns the stream.
|
||||||
|
//
|
||||||
// The base class calls this to obtain the object to
|
// The base class calls this to obtain the object to
|
||||||
// use for reading and writing HTTP messages.
|
// use for reading and writing HTTP messages.
|
||||||
//
|
//
|
||||||
@@ -297,7 +299,12 @@ class http_sync_port
|
|||||||
service_list<Services...> services_;
|
service_list<Services...> services_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
/** Constructor
|
||||||
|
|
||||||
|
@param instance The server instance which owns this port
|
||||||
|
|
||||||
|
@param log The stream to use for logging
|
||||||
|
*/
|
||||||
http_sync_port(
|
http_sync_port(
|
||||||
server& instance,
|
server& instance,
|
||||||
std::ostream& log)
|
std::ostream& log)
|
||||||
|
@@ -154,6 +154,10 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* This implementation class wraps the PortHandler and
|
||||||
|
manages the listening socket. Upon an incoming connection
|
||||||
|
it transfers ownership of the socket to the PortHandler.
|
||||||
|
*/
|
||||||
template<class PortHandler>
|
template<class PortHandler>
|
||||||
class port
|
class port
|
||||||
: public std::enable_shared_from_this<
|
: public std::enable_shared_from_this<
|
||||||
@@ -228,7 +232,11 @@ private:
|
|||||||
if(ec == boost::asio::error::operation_aborted)
|
if(ec == boost::asio::error::operation_aborted)
|
||||||
return;
|
return;
|
||||||
if(! ec)
|
if(! ec)
|
||||||
|
{
|
||||||
|
// Transfer ownership of the socket to the PortHandler
|
||||||
|
//
|
||||||
handler_.on_accept(std::move(sock_), ep_);
|
handler_.on_accept(std::move(sock_), ep_);
|
||||||
|
}
|
||||||
acceptor_.async_accept(sock_, ep_,
|
acceptor_.async_accept(sock_, ep_,
|
||||||
std::bind(&port::on_accept, this->shared_from_this(),
|
std::bind(&port::on_accept, this->shared_from_this(),
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
|
@@ -24,38 +24,6 @@ namespace framework {
|
|||||||
`true` if the request is processed or `false` if it does not
|
`true` if the request is processed or `false` if it does not
|
||||||
process the request.
|
process the request.
|
||||||
|
|
||||||
@b Service requirements
|
|
||||||
|
|
||||||
@code
|
|
||||||
|
|
||||||
struct Service
|
|
||||||
{
|
|
||||||
// Initialize the service
|
|
||||||
//
|
|
||||||
void
|
|
||||||
init(error_code& ec);
|
|
||||||
|
|
||||||
// Maybe respond to an HTTP request
|
|
||||||
//
|
|
||||||
// Returns `true` if it handled the response.
|
|
||||||
//
|
|
||||||
// Upon handling the response, the service may optionally
|
|
||||||
// take ownership of either the stream, the request, or both.
|
|
||||||
//
|
|
||||||
template<
|
|
||||||
class Stream,
|
|
||||||
class Body, class Fields,
|
|
||||||
class Send>
|
|
||||||
bool
|
|
||||||
respond(
|
|
||||||
Stream&&,
|
|
||||||
endpoint_type const& ep,
|
|
||||||
beast::http::request<Body, Fields>&& req,
|
|
||||||
Send const& send) const
|
|
||||||
};
|
|
||||||
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
@see file_service, ws_upgrade_service
|
@see file_service, ws_upgrade_service
|
||||||
*/
|
*/
|
||||||
template<class... Services>
|
template<class... Services>
|
||||||
|
@@ -35,9 +35,19 @@ template<
|
|||||||
bool isRequest, class Body, class Fields>
|
bool isRequest, class Body, class Fields>
|
||||||
class write_msg_op
|
class write_msg_op
|
||||||
{
|
{
|
||||||
|
// This composed operation has a state which is not trivial
|
||||||
|
// to copy (msg) so we need to store the state in an allocated
|
||||||
|
// object.
|
||||||
|
//
|
||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
|
// The stream we are writing to
|
||||||
AsyncWriteStream& stream;
|
AsyncWriteStream& stream;
|
||||||
|
|
||||||
|
// The message we are sending. Note that this composed
|
||||||
|
// operation takes ownership of the message and destroys
|
||||||
|
// it when it is done.
|
||||||
|
//
|
||||||
beast::http::message<isRequest, Body, Fields> msg;
|
beast::http::message<isRequest, Body, Fields> msg;
|
||||||
|
|
||||||
data(
|
data(
|
||||||
@@ -50,19 +60,40 @@ class write_msg_op
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `handler_ptr` is a utility which helps to manage a composed
|
||||||
|
// operation's state. It is similar to a shared pointer, but
|
||||||
|
// it uses handler allocation hooks to allocate and free memory,
|
||||||
|
// and it also helps to meet Asio's deallocate-before-invocation
|
||||||
|
// guarantee.
|
||||||
|
//
|
||||||
beast::handler_ptr<data, Handler> d_;
|
beast::handler_ptr<data, Handler> d_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Asio can move and copy the handler, we support both
|
||||||
write_msg_op(write_msg_op&&) = default;
|
write_msg_op(write_msg_op&&) = default;
|
||||||
write_msg_op(write_msg_op const&) = default;
|
write_msg_op(write_msg_op const&) = default;
|
||||||
|
|
||||||
template<class DeducedHandler, class... Args>
|
// Constructor
|
||||||
write_msg_op(DeducedHandler&& h, AsyncWriteStream& s, Args&&... args)
|
//
|
||||||
|
// We take the handler as a template type to
|
||||||
|
// support both const and rvalue references.
|
||||||
|
//
|
||||||
|
template<
|
||||||
|
class DeducedHandler,
|
||||||
|
class... Args>
|
||||||
|
write_msg_op(
|
||||||
|
DeducedHandler&& h,
|
||||||
|
AsyncWriteStream& s,
|
||||||
|
Args&&... args)
|
||||||
: d_(std::forward<DeducedHandler>(h),
|
: d_(std::forward<DeducedHandler>(h),
|
||||||
s, std::forward<Args>(args)...)
|
s, std::forward<Args>(args)...)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Entry point
|
||||||
|
//
|
||||||
|
// The initiation function calls this to start the operation
|
||||||
|
//
|
||||||
void
|
void
|
||||||
operator()()
|
operator()()
|
||||||
{
|
{
|
||||||
@@ -71,12 +102,22 @@ public:
|
|||||||
d.stream, d.msg, std::move(*this));
|
d.stream, d.msg, std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Completion handler
|
||||||
|
//
|
||||||
|
// This gets called when beast::http::async_write completes
|
||||||
|
//
|
||||||
void
|
void
|
||||||
operator()(error_code ec)
|
operator()(error_code ec)
|
||||||
{
|
{
|
||||||
d_.invoke(ec);
|
d_.invoke(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// These hooks are necessary for Asio
|
||||||
|
//
|
||||||
|
// The meaning is explained in the Beast documentation
|
||||||
|
//
|
||||||
|
|
||||||
friend
|
friend
|
||||||
void* asio_handler_allocate(
|
void* asio_handler_allocate(
|
||||||
std::size_t size, write_msg_op* op)
|
std::size_t size, write_msg_op* op)
|
||||||
|
@@ -21,13 +21,11 @@ namespace framework {
|
|||||||
// This object holds the state of the connection
|
// This object holds the state of the connection
|
||||||
// including, most importantly, the socket or stream.
|
// including, most importantly, the socket or stream.
|
||||||
//
|
//
|
||||||
// `Stream` is the type of socket or stream used as the
|
|
||||||
// transport. Examples include boost::asio::ip::tcp::socket
|
|
||||||
// or `ssl_stream`.
|
|
||||||
//
|
//
|
||||||
template<class Derived>
|
template<class Derived>
|
||||||
class async_ws_con
|
class async_ws_con
|
||||||
{
|
{
|
||||||
|
// This function lets us access members of the derived class
|
||||||
Derived&
|
Derived&
|
||||||
impl()
|
impl()
|
||||||
{
|
{
|
||||||
@@ -201,12 +199,28 @@ private:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This class represents an asynchronous WebSocket connection
|
||||||
|
// which uses a plain TCP/IP socket (no encryption) as the stream.
|
||||||
|
//
|
||||||
class async_ws_con_plain
|
class async_ws_con_plain
|
||||||
|
|
||||||
|
// Note that we give this object the `enable_shared_from_this`, and have
|
||||||
|
// the base class call `impl().shared_from_this()` when needed.
|
||||||
|
//
|
||||||
: public std::enable_shared_from_this<async_ws_con_plain>
|
: public std::enable_shared_from_this<async_ws_con_plain>
|
||||||
|
|
||||||
|
// We want the socket to be created before the base class so we use
|
||||||
|
// the "base from member" idiom which Boost provides as a class.
|
||||||
|
//
|
||||||
, public base_from_member<beast::websocket::stream<socket_type>>
|
, public base_from_member<beast::websocket::stream<socket_type>>
|
||||||
|
|
||||||
|
// Declare this base last now that everything else got set up first.
|
||||||
|
//
|
||||||
, public async_ws_con<async_ws_con_plain>
|
, public async_ws_con<async_ws_con_plain>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Construct the plain connection.
|
||||||
|
//
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
explicit
|
explicit
|
||||||
async_ws_con_plain(
|
async_ws_con_plain(
|
||||||
@@ -217,6 +231,10 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the stream.
|
||||||
|
//
|
||||||
|
// The base class calls this to obtain the websocket stream object.
|
||||||
|
//
|
||||||
beast::websocket::stream<socket_type>&
|
beast::websocket::stream<socket_type>&
|
||||||
ws()
|
ws()
|
||||||
{
|
{
|
||||||
@@ -226,7 +244,7 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/** An synchronous WebSocket @b PortHandler which implements echo.
|
/** An asynchronous WebSocket @b PortHandler which implements echo.
|
||||||
|
|
||||||
This is a port handler which accepts WebSocket upgrade HTTP
|
This is a port handler which accepts WebSocket upgrade HTTP
|
||||||
requests and implements the echo protocol. All received
|
requests and implements the echo protocol. All received
|
||||||
@@ -272,10 +290,10 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Accept a TCP/IP async_ws_con.
|
/** Accept a TCP/IP connection.
|
||||||
|
|
||||||
This function is called when the server has accepted an
|
This function is called when the server has accepted an
|
||||||
incoming async_ws_con.
|
incoming connection.
|
||||||
|
|
||||||
@param sock The connected socket.
|
@param sock The connected socket.
|
||||||
|
|
||||||
@@ -298,10 +316,10 @@ public:
|
|||||||
|
|
||||||
/** Accept a WebSocket upgrade request.
|
/** Accept a WebSocket upgrade request.
|
||||||
|
|
||||||
This is used to accept a async_ws_con that has already
|
This is used to accept a connection that has already
|
||||||
delivered the handshake.
|
delivered the handshake.
|
||||||
|
|
||||||
@param stream The stream corresponding to the async_ws_con.
|
@param stream The stream corresponding to the connection.
|
||||||
|
|
||||||
@param ep The remote endpoint.
|
@param ep The remote endpoint.
|
||||||
|
|
||||||
@@ -310,12 +328,12 @@ public:
|
|||||||
template<class Body, class Fields>
|
template<class Body, class Fields>
|
||||||
void
|
void
|
||||||
accept(
|
accept(
|
||||||
socket_type&& stream,
|
socket_type&& sock,
|
||||||
endpoint_type ep,
|
endpoint_type ep,
|
||||||
beast::http::request<Body, Fields>&& req)
|
beast::http::request<Body, Fields>&& req)
|
||||||
{
|
{
|
||||||
std::make_shared<async_ws_con_plain>(
|
std::make_shared<async_ws_con_plain>(
|
||||||
std::move(stream),
|
std::move(sock),
|
||||||
"ws_async_port",
|
"ws_async_port",
|
||||||
log_,
|
log_,
|
||||||
instance_.next_id(),
|
instance_.next_id(),
|
||||||
|
@@ -19,16 +19,20 @@
|
|||||||
|
|
||||||
namespace framework {
|
namespace framework {
|
||||||
|
|
||||||
// The connection object holds the state of the connection
|
/** A synchronous WebSocket connection.
|
||||||
// including, most importantly, the socket or stream.
|
|
||||||
//
|
This base class implements a WebSocket connection object
|
||||||
// `Stream` is the type of socket or stream used as the
|
using synchronous calls.
|
||||||
// transport. Examples include boost::asio::ip::tcp::socket
|
|
||||||
// or `ssl_stream`.
|
It uses the Curiously Recurring Template pattern (CRTP) where
|
||||||
//
|
we refer to the derived class in order to access the stream object
|
||||||
|
to use for reading and writing. This lets the same class be used
|
||||||
|
for plain and SSL stream objects.
|
||||||
|
*/
|
||||||
template<class Derived>
|
template<class Derived>
|
||||||
class sync_ws_con
|
class sync_ws_con
|
||||||
{
|
{
|
||||||
|
// This function lets us access members of the derived class
|
||||||
Derived&
|
Derived&
|
||||||
impl()
|
impl()
|
||||||
{
|
{
|
||||||
@@ -237,12 +241,28 @@ private:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This class represents a synchronous WebSocket connection
|
||||||
|
// which uses a plain TCP/IP socket (no encryption) as the stream.
|
||||||
|
//
|
||||||
class sync_ws_con_plain
|
class sync_ws_con_plain
|
||||||
|
|
||||||
|
// Note that we give this object the `enable_shared_from_this`, and have
|
||||||
|
// the base class call `impl().shared_from_this()` when needed.
|
||||||
|
//
|
||||||
: public std::enable_shared_from_this<sync_ws_con_plain>
|
: public std::enable_shared_from_this<sync_ws_con_plain>
|
||||||
|
|
||||||
|
// We want the socket to be created before the base class so we use
|
||||||
|
// the "base from member" idiom which Boost provides as a class.
|
||||||
|
//
|
||||||
, public base_from_member<beast::websocket::stream<socket_type>>
|
, public base_from_member<beast::websocket::stream<socket_type>>
|
||||||
|
|
||||||
|
// Declare this base last now that everything else got set up first.
|
||||||
|
//
|
||||||
, public sync_ws_con<sync_ws_con_plain>
|
, public sync_ws_con<sync_ws_con_plain>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Construct the plain connection.
|
||||||
|
//
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
explicit
|
explicit
|
||||||
sync_ws_con_plain(
|
sync_ws_con_plain(
|
||||||
@@ -253,6 +273,10 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the stream.
|
||||||
|
//
|
||||||
|
// The base class calls this to obtain the websocket stream object.
|
||||||
|
//
|
||||||
beast::websocket::stream<socket_type>&
|
beast::websocket::stream<socket_type>&
|
||||||
ws()
|
ws()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user