Documentation revision

fix #567, fix #572
This commit is contained in:
Vinnie Falco
2017-06-28 18:30:59 -07:00
parent 8b5b8335e6
commit 2843a497a0
11 changed files with 130 additions and 108 deletions

View File

@@ -1,6 +1,7 @@
Version 71: Version 71:
* Fix extra ; warning * Fix extra ; warning
* Documentation revision
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@@ -109,7 +109,7 @@ cmake -G Xcode .. # for Apple Xcode builds
cd .. cd ..
mkdir bin64 mkdir bin64
cd ../bin64 cd bin64
cmake -G"Visual Studio 14 2015 Win64" .. # for 64-bit Windows builds (VS2015) cmake -G"Visual Studio 14 2015 Win64" .. # for 64-bit Windows builds (VS2015)
cmake -G"Visual Studio 15 2017 Win64" .. # for 64-bit Windows builds (VS2017) cmake -G"Visual Studio 15 2017 Win64" .. # for 64-bit Windows builds (VS2017)

View File

@@ -97,7 +97,7 @@ lightweight iterators over the existing, unmodified memory buffers.
Control of buffers is retained by the caller; ownership is not Control of buffers is retained by the caller; ownership is not
transferred. transferred.
[table Buffer Algorithms [table Buffer Algorithms and Types
[[Name][Description]] [[Name][Description]]
[[ [[
[link beast.ref.beast__buffer_cat `buffer_cat`] [link beast.ref.beast__buffer_cat `buffer_cat`]
@@ -126,7 +126,7 @@ transferred.
][ ][
This class represents the buffer sequence formed from a prefix of This class represents the buffer sequence formed from a prefix of
an existing buffer sequence. This is the type of buffer returned by an existing buffer sequence. This is the type of buffer returned by
[link beast.ref.beast__buffer_prefix `buffer_prefix`]. [link beast.ref.beast__buffer_prefix.overload3 `buffer_prefix`].
]] ]]
[[ [[
[link beast.ref.beast__consuming_buffers `consuming_buffers`] [link beast.ref.beast__consuming_buffers `consuming_buffers`]

View File

@@ -22,7 +22,7 @@ at once, such as:
These types of operations require callers to manage the lifetime of These types of operations require callers to manage the lifetime of
associated state, by constructing a class derived from __basic_parser__. associated state, by constructing a class derived from __basic_parser__.
Beast comes with the derived instance __parser__ which creates complete Beast comes with the derived instance __parser__ which creates complete
__message__ objects; user-defined parsers are also possible: __message__ objects using the __basic_fields__ Fields container.
[table Parser [table Parser
[[Name][Description]] [[Name][Description]]
@@ -32,9 +32,9 @@ __message__ objects; user-defined parsers are also possible:
``` ```
/// An HTTP/1 parser for producing a message. /// An HTTP/1 parser for producing a message.
template< template<
bool isRequest, // `true` to parse an HTTP request bool isRequest, // `true` to parse an HTTP request
class Body, // The Body type for the resulting message class Body, // The Body type for the resulting message
class Fields = fields> // The type of container representing the fields class Allocator = std::allocator<char>> // The type of allocator for the header
class parser class parser
: public basic_parser<...>; : public basic_parser<...>;
``` ```
@@ -44,8 +44,8 @@ __message__ objects; user-defined parsers are also possible:
][ ][
``` ```
/// An HTTP/1 parser for producing a request message. /// An HTTP/1 parser for producing a request message.
template<class Body, class Fields = fields> template<class Body, class Allocator = std::allocator<char>>
using request_parser = parser<true, Body, Fields>; using request_parser = parser<true, Body, Allocator>;
``` ```
]] ]]
[[ [[
@@ -53,8 +53,8 @@ __message__ objects; user-defined parsers are also possible:
][ ][
``` ```
/// An HTTP/1 parser for producing a response message. /// An HTTP/1 parser for producing a response message.
template<class Body, class Fields = fields> template<class Body, class Allocator = std::allocator<char>>
using response_parser = parser<false, Body, Fields>; using response_parser = parser<false, Body, Allocator>;
``` ```
]] ]]
] ]

View File

@@ -9,11 +9,11 @@
While the parsers included in the library will handle a broad number of While the parsers included in the library will handle a broad number of
use-cases, the __basic_parser__ interface can be subclassed to implement use-cases, the __basic_parser__ interface can be subclassed to implement
custom parsing strategies: the parser processes the incoming octets into custom parsing strategies: the basic parser processes the incoming octets
elements according to the HTTP/1 protocol specification, while the derived into elements according to the HTTP/1 protocol specification, while the
class decides what to do with those elements. In particular, users who derived class decides what to do with those elements. In particular, users
create exotic containers for [*Fields] may need to also create their own who create exotic containers for [*Fields] may need to also create their
parser. Custom parsers will work with all of the stream read operations own parser. Custom parsers will work with all of the stream read operations
that work on parsers, as those algorithms use only the basic parser that work on parsers, as those algorithms use only the basic parser
interface. Some use cases for implementing custom parsers are: interface. Some use cases for implementing custom parsers are:

View File

@@ -22,10 +22,10 @@ The connection is considered gracefully closed when each side has sent
and received a close frame. and received a close frame.
During read operations, Beast automatically reads and processes control During read operations, Beast automatically reads and processes control
frames. Pings are replied to as soon as possible with a pong, received frames. If a control callback is registered, the callback is notified of
ping and pongs are delivered to the ping callback. The receipt of a close the incoming control frame. The implementation will respond to pings
frame initiates the WebSocket close procedure, eventually resulting in the automatically. The receipt of a close frame initiates the WebSocket
error code close procedure, eventually resulting in the error code
[link beast.ref.beast__websocket__error `error::closed`] [link beast.ref.beast__websocket__error `error::closed`]
being delivered to the caller in a subsequent read operation, assuming being delivered to the caller in a subsequent read operation, assuming
no other error takes place. no other error takes place.
@@ -35,36 +35,39 @@ operations can cause socket writes. However, these writes will not
compete with caller-initiated write operations. For the purposes of compete with caller-initiated write operations. For the purposes of
correctness with respect to the stream invariants, caller-initiated correctness with respect to the stream invariants, caller-initiated
read operations still only count as a read. This means that callers can read operations still only count as a read. This means that callers can
have a simultaneously active read, write, and ping operation in progress, have a simultaneously active read, write, and ping/pong operation in
while the implementation also automatically handles control frames. progress, while the implementation also automatically handles control
frames.
[heading Control Callback] [heading Control Callback]
Ping and pong messages are control frames which may be sent at any time Ping, pong, and close messages are control frames which may be sent at
by either peer on an established WebSocket connection. They are sent any time by either peer on an established WebSocket connection. They
using the functions are sent using the functions
[link beast.ref.beast__websocket__stream.ping `ping`] and [link beast.ref.beast__websocket__stream.ping `ping`],
[link beast.ref.beast__websocket__stream.pong `pong`]. [link beast.ref.beast__websocket__stream.pong `pong`].
To be notified of control frames, including pings, pongs, and close frames, and
callers may register a ['control callback] using [link beast.ref.beast__websocket__stream.close `close`].
To be notified of control frames, callers may register a
['control callback] using
[link beast.ref.beast__websocket__stream.control_callback `control_callback`]. [link beast.ref.beast__websocket__stream.control_callback `control_callback`].
The object provided with this option should be callable with the following The object provided with this option should be callable with the following
signature: signature:
[ws_snippet_17] [ws_snippet_17]
When a ping callback is registered, all pings and pongs received through When a control callback is registered, it will be invoked for all pings,
either synchronous read functions or asynchronous read functions will pongs, and close frames received through either synchronous read functions
invoke the ping callback, with the value of `is_pong` set to `true` if a or asynchronous read functions. The type of frame and payload text are
pong was received or `false` otherwise. The payload of the ping or pong passed as parameters to the control callback. If the frame is a close
control frame is passed in the payload argument. frame, the close reason may be obtained by calling
[link beast.ref.beast__websocket__stream.reason `reason`].
Unlike regular completion handlers used in calls to asynchronous initiation Unlike regular completion handlers used in calls to asynchronous initiation
functions, the ping callback only needs to be set once. The callback is not functions, the control callback only needs to be set once. The callback is
reset when a ping or pong is received. The same callback is used for both not reset after being called. The same callback is used for both synchronous
synchronous and asynchronous reads. The ping callback is passive; in order and asynchronous reads. The callback is passive; in order to be called,
to receive pings and pongs, a synchronous or asynchronous stream read a stream read operation must be active.
function must be active.
[note [note
When an asynchronous read function receives a control frame, the When an asynchronous read function receives a control frame, the

View File

@@ -124,8 +124,22 @@ void f(message<isRequest, Fields, Body>& msg);
``` ```
This function can manipulate the fields common to requests and responses. This function can manipulate the fields common to requests and responses.
If it needs to access the other fields, it can do so using tag dispatch If it needs to access the other fields, it can use overloads with
with an object of type `std::integral_constant<bool, isRequest>`. partial specialization, or in C++17 a `constexpr` expression:
```
template<bool isRequest, class Fields, class Body>
void f(message<isRequest, Fields, Body>& msg)
{
if constexpr(isRequest)
{
// call msg.method(), msg.target()
}
else
{
// call msg.result(), msg.reason()
}
}
```
Often, in non-trivial HTTP applications, we want to read the HTTP header Often, in non-trivial HTTP applications, we want to read the HTTP header
and examine its contents before choosing a type for [*Body]. To accomplish and examine its contents before choosing a type for [*Body]. To accomplish

View File

@@ -24,36 +24,33 @@ about Beast and other HTTP libraries that have gone through formal review.
[[ [[
"Beast does not offer an HTTP server?" "Beast does not offer an HTTP server?"
][ ][
The scope of the library is to provide a message container, Beast has a functional HTTP server in the example directory. The
and serialization and deserialization algorithms, with an server supports both HTTP and WebSocket using synchronous and
interface permitting users to achieve all the behaviors asynchronous shared or dedicated ports. In addition, the server
necessary to implement high performance, conforming servers. supports encrypted TLS connections if OpenSSL is available, on
However, management of listening sockets, io_service threads, dedicated ports. And the server comes with a "multi-port", a
individual connections, and HTTP semantics such as pipelining, flexible single port which supports both encrypted and unencrypted
redirection, Expect: 100-continue, cookies, and request routing connections, both HTTP and WebSocket, all on the same port. The
are not handled by Beast. server is not part of Beast's public interfaces, as that
It is the author's position that keeping the library low-level functionality is outside the scope of the library. The author
will establish it as a building block which the greater C++ feels that attempting to broaden the scope of the library will
community at large can leverage to produce higher level reduce its appeal for standardization.
libraries competing with each other to figure out the best
way to solve these problems.
]] ]]
[[ [[
"Beast does not offer an HTTP client?" "Beast does not offer an HTTP client?"
][ ][
"I just want to download a resource using HTTP" is a common "I just want to download a resource using HTTP" is a common
cry from users and reviewers. Such functionality is beyond cry from users and reviewers. Such functionality is beyond
the scope of Beast and will likely never be added. Building the scope of Beast. Building a full featured HTTP client is
a robust HTTP client is a difficult task. The source code for a difficult task and large enough to deserve its own library.
such a client would probably be several times larger than There are many things to deal with such as the various message
the entirety of Beast! There are many things to deal with body encodings, complex parsing of headers, difficult header
such as the various message body encodings, complex parsing semantics such as Range and Cache-Control, redirection,
of headers, difficult header semantics such as Range and Expect:100-continue, connection retrying, domain name
Cache-Control, redirection, Expect:100-continue, connection resolution, TLS, and much, much more. It is the author's
retrying, domain name resolution, TLS, and much, much more. position that Boost first needs a common set of nouns and
It is the author's position that Boost first needs a common verbs for manipulating HTTP at the protocol level; Beast
set of nouns and verbs for manipulating HTTP at the protocol provides that language.
level; Beast provides that language.
]] ]]
[[ [[
"There's no HTTP/2 support yet!" "There's no HTTP/2 support yet!"
@@ -86,17 +83,15 @@ about Beast and other HTTP libraries that have gone through formal review.
[[ [[
"This should work with standalone-Asio!" "This should work with standalone-Asio!"
][ ][
Beast uses more than Boost.Asio, it depends on a smattering Beast uses more than Boost.Asio, it depends on various other parts
of various parts of Boost. The standalone Asio is currently of Boost. The standalone Asio is currently farther ahead than the
farther ahead than the Boost version. Keeping Beast maintained Boost version. Keeping Beast maintained against both versions of
against both versions of Asio is beyond the resources of the Asio is beyond the resources of the author at the present time.
author at the present time. Compatibility with non-Boost Compatibility with non-Boost libraries should not be an acceptance
libraries should not be an acceptance criteria. Beast is criteria. Beast is currently designed to be a part of Boost:
currently designed to be a part of Boost: nothing more, nothing more, nothing less. Looking at the bigger picture, it
nothing less. is the author's goal to propose this library for standardization.
Looking at the bigger picture, it is the author's goal to A logical track for achieving this is as follows:
propose this library for standardization. A logical track for
achieving this is as follows:
[ordered_list [ordered_list
[ [
@@ -130,7 +125,9 @@ about Beast and other HTTP libraries that have gone through formal review.
As the library matures it will undergo optimization passes; benchmarks As the library matures it will undergo optimization passes; benchmarks
will logically accompany this process. There is a small benchmarking will logically accompany this process. There is a small benchmarking
program included in the tests which compares the performance of program included in the tests which compares the performance of
Beast's parser to the NodeJS reference parser. Beast's parser to the NodeJS reference parser, as well as some
benchmarks which compare the performance of various Beast dynamic
buffer implementations against Asio's.
]] ]]
[[ [[
"Beast is a terrible name!" "Beast is a terrible name!"
@@ -164,12 +161,13 @@ about Beast and other HTTP libraries that have gone through formal review.
"Some more advanced examples, e.g. including TLS with client/server "Some more advanced examples, e.g. including TLS with client/server
certificates would help." certificates would help."
][ ][
The HTTP interface doesn't try to reinvent the wheel, it just uses The server-framework example demonstrates how to implement a server
the `boost::asio::ip::tcp::socket` or `boost::asio::ssl::stream` that that supports TLS using certificates. There are also websocket and
you set up beforehand. Callers use the interfaces already existing HTTP client examples which use TLS. Furthermore, management of
on those objects to make outgoing connections, accept incoming connections, certificates is beyond the scope of the public interfaces of the
or establish TLS sessions with certificates. We find the available Asio library. Asio already provides documentation, interfaces, and
examples for performing these tasks sufficient. examples for performing these tasks - Beast does not intend to
reinvent them or to redundantly provide this information.
]] ]]
[[ [[
@@ -178,14 +176,17 @@ about Beast and other HTTP libraries that have gone through formal review.
We presume this means a facility to match expressions against the URI We presume this means a facility to match expressions against the URI
in HTTP requests, and dispatch them to calling code. The authors feel in HTTP requests, and dispatch them to calling code. The authors feel
that this is a responsibility of higher level code. Beast does that this is a responsibility of higher level code. Beast does
not try to offer a web server. not try to offer a web server. That said, the server-framework
example has a concept of request routing called a Service. Two
services are provided, one for serving files and the other for
handling WebSocket upgrade requests.
]] ]]
[[ [[
"HTTP Cookies? Forms/File Uploads?" "HTTP Cookies? Forms/File Uploads?"
][ ][
Cookies, or managing these types of HTTP headers in general, is the Cookies, or managing these types of HTTP headers in general, is the
responsibility of higher levels. Beast.HTTP just tries to get complete responsibility of higher levels. Beast just tries to get complete
messages to and from the calling code. It deals in the HTTP headers just messages to and from the calling code. It deals in the HTTP headers just
enough to process the message body and leaves the rest to callers. However, enough to process the message body and leaves the rest to callers. However,
for forms and file uploads the symmetric interface of the message class for forms and file uploads the symmetric interface of the message class
@@ -197,11 +198,8 @@ about Beast and other HTTP libraries that have gone through formal review.
"...supporting TLS (is this a feature? If not this would be a show-stopper), "...supporting TLS (is this a feature? If not this would be a show-stopper),
etc." etc."
][ ][
Beast does not provide direct facilities for implementing TLS connections; Beast works with the Stream concept, so it automatically works with the
however, the interfaces already existing on the `boost::asio::ssl::stream` `boost::asio::ssl::stream` that you have already set up through Asio.
are available and can be used to establish secure connections. Then,
functions like `http::read` or `http::async_write` can work with those
encrypted connections with no problem.
]] ]]
[[ [[
@@ -215,18 +213,18 @@ about Beast and other HTTP libraries that have gone through formal review.
which higher abstractions such as the aforementioned HTTP service or which higher abstractions such as the aforementioned HTTP service or
cgi-gateway can be built. cgi-gateway can be built.
One of the example programs implements a simple HTTP server that There are several HTTP servers in the example directory which deliver
delivers files from the filesystem. files, as well as some tested and compiled code snippets which can be
used as a starting point for interfacing with other processes.
]] ]]
[[ [[
"You should send a 100-continue to ask for the rest of the body if required." "You should send a 100-continue to ask for the rest of the body if required."
][ ][
The Beast interface supports this functionality (by allowing this Deciding on whether to send the "Expect: 100-continue" header or
special case of "split" message parsing and serialization). Specifically, how to handle it on the server side is the caller's responsibility;
it lets callers read the request up to just before the body, Beast provides the functionality to send or inspect the header before
and let callers write the request up to just before the body. However, sending or reading the body.
making use of this behavior is up to callers (since Beast is low level).
]] ]]
@@ -236,13 +234,18 @@ about Beast and other HTTP libraries that have gone through formal review.
in production. That would give some evidence that the design in production. That would give some evidence that the design
works in practice." works in practice."
][ ][
Beast.HTTP and Beast.WebSocket are production ready and currently Beast has already been on public servers receiving traffic and handling
running on public servers receiving traffic and handling millions of hundreds of millions of dollars' worth of financial transactions daily.
dollars' worth of financial transactions daily. The servers run [*rippled], The servers run [*rippled], open source software
open source software ([@https://github.com/ripple/rippled repository]) ([@https://github.com/ripple/rippled repository])
implementing the implementing the
[@https://ripple.com/files/ripple_consensus_whitepaper.pdf [*Ripple Consensus Protocol]], [@https://ripple.com/files/ripple_consensus_whitepaper.pdf [*Ripple Consensus Protocol]],
technology provided by [@http://ripple.com Ripple]. technology provided by [@http://ripple.com Ripple].
Furthermore, the repository has grown significantly in popularity in
2017. There are many users, and some of them participate directly in
the repository by reporting issues, performing testing, and in some
cases submitting pull requests with code contributions.
]] ]]
@@ -263,8 +266,8 @@ about Beast and other HTTP libraries that have gone through formal review.
`boost::asio::ssl::stream`). You establish your TLS connection using the `boost::asio::ssl::stream`). You establish your TLS connection using the
interface on `ssl::stream` like shown in all of the Asio examples, then interface on `ssl::stream` like shown in all of the Asio examples, then
construct your `websocket::stream` around it. It works perfectly fine; construct your `websocket::stream` around it. It works perfectly fine;
Beast.WebSocket doesn't try to reinvent the wheel or put a fresh coat of Beast comes with an `ssl_stream` wrapper in the example directory which
interface paint on the `ssl::stream`. allows the SSL stream to be moved, overcoming an Asio limitation.
The WebSocket implementation [*does] provide support for shutting down The WebSocket implementation [*does] provide support for shutting down
the TLS connection through the use of the ADL compile-time virtual functions the TLS connection through the use of the ADL compile-time virtual functions

View File

@@ -49,7 +49,7 @@ int main()
// Wrap the now-connected socket in a websocket stream // Wrap the now-connected socket in a websocket stream
websocket::stream<tcp::socket&> ws{sock}; websocket::stream<tcp::socket&> ws{sock};
// Perform the websocket handhskae // Perform the websocket handshake
ws.handshake(host, "/", ec); ws.handshake(host, "/", ec);
if(ec) if(ec)
return fail("handshake", ec); return fail("handshake", ec);

View File

@@ -101,7 +101,7 @@ public:
#if BEAST_DOXYGEN #if BEAST_DOXYGEN
template<class... Args> template<class... Args>
explicit explicit
msesage_parser(Args&&... args); parser(Args&&... args);
#else #else
template<class Arg1, class... ArgN, template<class Arg1, class... ArgN,
class = typename std::enable_if< class = typename std::enable_if<
@@ -195,8 +195,8 @@ public:
/** Set the on_header callback. /** Set the on_header callback.
This optional callback is invoked after the parser receives When the callback is set, it is called after the parser
a complete header. The function must be invokable with receives a complete header. The function must be invocable with
this signature: this signature:
@code @code
void callback( void callback(
@@ -212,7 +212,7 @@ public:
void void
on_header(std::function<void(parser&, error_code&)> cb) on_header(std::function<void(parser&, error_code&)> cb)
{ {
cb_ = cb; cb_ = std::move(cb);
} }
private: private:

View File

@@ -123,7 +123,8 @@ void fxx() {
//[http_snippet_10 //[http_snippet_10
response<string_body> res; response<string_body> res;
response_serializer<string_body, fields> sr{res};
response_serializer<string_body> sr{res};
//] //]
} }