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:
* Fix extra ; warning
* Documentation revision
--------------------------------------------------------------------------------

View File

@ -109,7 +109,7 @@ cmake -G Xcode .. # for Apple Xcode builds
cd ..
mkdir bin64
cd ../bin64
cd bin64
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)

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
transferred.
[table Buffer Algorithms
[table Buffer Algorithms and Types
[[Name][Description]]
[[
[link beast.ref.beast__buffer_cat `buffer_cat`]
@ -126,7 +126,7 @@ transferred.
][
This class represents the buffer sequence formed from a prefix of
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`]

View File

@ -22,7 +22,7 @@ at once, such as:
These types of operations require callers to manage the lifetime of
associated state, by constructing a class derived from __basic_parser__.
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
[[Name][Description]]
@ -32,9 +32,9 @@ __message__ objects; user-defined parsers are also possible:
```
/// An HTTP/1 parser for producing a message.
template<
bool isRequest, // `true` to parse an HTTP request
class Body, // The Body type for the resulting message
class Fields = fields> // The type of container representing the fields
bool isRequest, // `true` to parse an HTTP request
class Body, // The Body type for the resulting message
class Allocator = std::allocator<char>> // The type of allocator for the header
class 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.
template<class Body, class Fields = fields>
using request_parser = parser<true, Body, Fields>;
template<class Body, class Allocator = std::allocator<char>>
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.
template<class Body, class Fields = fields>
using response_parser = parser<false, Body, Fields>;
template<class Body, class Allocator = std::allocator<char>>
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
use-cases, the __basic_parser__ interface can be subclassed to implement
custom parsing strategies: the parser processes the incoming octets into
elements according to the HTTP/1 protocol specification, while the derived
class decides what to do with those elements. In particular, users who
create exotic containers for [*Fields] may need to also create their own
parser. Custom parsers will work with all of the stream read operations
custom parsing strategies: the basic parser processes the incoming octets
into elements according to the HTTP/1 protocol specification, while the
derived class decides what to do with those elements. In particular, users
who create exotic containers for [*Fields] may need to also create their
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
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.
During read operations, Beast automatically reads and processes control
frames. Pings are replied to as soon as possible with a pong, received
ping and pongs are delivered to the ping callback. The receipt of a close
frame initiates the WebSocket close procedure, eventually resulting in the
error code
frames. If a control callback is registered, the callback is notified of
the incoming control frame. The implementation will respond to pings
automatically. The receipt of a close frame initiates the WebSocket
close procedure, eventually resulting in the error code
[link beast.ref.beast__websocket__error `error::closed`]
being delivered to the caller in a subsequent read operation, assuming
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
correctness with respect to the stream invariants, caller-initiated
read operations still only count as a read. This means that callers can
have a simultaneously active read, write, and ping operation in progress,
while the implementation also automatically handles control frames.
have a simultaneously active read, write, and ping/pong operation in
progress, while the implementation also automatically handles control
frames.
[heading Control Callback]
Ping and pong messages are control frames which may be sent at any time
by either peer on an established WebSocket connection. They are sent
using the functions
[link beast.ref.beast__websocket__stream.ping `ping`] and
Ping, pong, and close messages are control frames which may be sent at
any time by either peer on an established WebSocket connection. They
are sent using the functions
[link beast.ref.beast__websocket__stream.ping `ping`],
[link beast.ref.beast__websocket__stream.pong `pong`].
To be notified of control frames, including pings, pongs, and close frames,
callers may register a ['control callback] using
and
[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`].
The object provided with this option should be callable with the following
signature:
[ws_snippet_17]
When a ping callback is registered, all pings and pongs received through
either synchronous read functions or asynchronous read functions will
invoke the ping callback, with the value of `is_pong` set to `true` if a
pong was received or `false` otherwise. The payload of the ping or pong
control frame is passed in the payload argument.
When a control callback is registered, it will be invoked for all pings,
pongs, and close frames received through either synchronous read functions
or asynchronous read functions. The type of frame and payload text are
passed as parameters to the control callback. If the frame is a close
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
functions, the ping callback only needs to be set once. The callback is not
reset when a ping or pong is received. The same callback is used for both
synchronous and asynchronous reads. The ping callback is passive; in order
to receive pings and pongs, a synchronous or asynchronous stream read
function must be active.
functions, the control callback only needs to be set once. The callback is
not reset after being called. The same callback is used for both synchronous
and asynchronous reads. The callback is passive; in order to be called,
a stream read operation must be active.
[note
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.
If it needs to access the other fields, it can do so using tag dispatch
with an object of type `std::integral_constant<bool, isRequest>`.
If it needs to access the other fields, it can use overloads with
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
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?"
][
The scope of the library is to provide a message container,
and serialization and deserialization algorithms, with an
interface permitting users to achieve all the behaviors
necessary to implement high performance, conforming servers.
However, management of listening sockets, io_service threads,
individual connections, and HTTP semantics such as pipelining,
redirection, Expect: 100-continue, cookies, and request routing
are not handled by Beast.
It is the author's position that keeping the library low-level
will establish it as a building block which the greater C++
community at large can leverage to produce higher level
libraries competing with each other to figure out the best
way to solve these problems.
Beast has a functional HTTP server in the example directory. The
server supports both HTTP and WebSocket using synchronous and
asynchronous shared or dedicated ports. In addition, the server
supports encrypted TLS connections if OpenSSL is available, on
dedicated ports. And the server comes with a "multi-port", a
flexible single port which supports both encrypted and unencrypted
connections, both HTTP and WebSocket, all on the same port. The
server is not part of Beast's public interfaces, as that
functionality is outside the scope of the library. The author
feels that attempting to broaden the scope of the library will
reduce its appeal for standardization.
]]
[[
"Beast does not offer an HTTP client?"
][
"I just want to download a resource using HTTP" is a common
cry from users and reviewers. Such functionality is beyond
the scope of Beast and will likely never be added. Building
a robust HTTP client is a difficult task. The source code for
such a client would probably be several times larger than
the entirety of Beast! There are many things to deal with
such as the various message body encodings, complex parsing
of headers, difficult header semantics such as Range and
Cache-Control, redirection, Expect:100-continue, connection
retrying, domain name resolution, TLS, and much, much more.
It is the author's position that Boost first needs a common
set of nouns and verbs for manipulating HTTP at the protocol
level; Beast provides that language.
the scope of Beast. Building a full featured HTTP client is
a difficult task and large enough to deserve its own library.
There are many things to deal with such as the various message
body encodings, complex parsing of headers, difficult header
semantics such as Range and Cache-Control, redirection,
Expect:100-continue, connection retrying, domain name
resolution, TLS, and much, much more. It is the author's
position that Boost first needs a common set of nouns and
verbs for manipulating HTTP at the protocol level; Beast
provides that language.
]]
[[
"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!"
][
Beast uses more than Boost.Asio, it depends on a smattering
of various parts of Boost. The standalone Asio is currently
farther ahead than the Boost version. Keeping Beast maintained
against both versions of Asio is beyond the resources of the
author at the present time. Compatibility with non-Boost
libraries should not be an acceptance criteria. Beast is
currently designed to be a part of Boost: nothing more,
nothing less.
Looking at the bigger picture, it is the author's goal to
propose this library for standardization. A logical track for
achieving this is as follows:
Beast uses more than Boost.Asio, it depends on various other parts
of Boost. The standalone Asio is currently farther ahead than the
Boost version. Keeping Beast maintained against both versions of
Asio is beyond the resources of the author at the present time.
Compatibility with non-Boost libraries should not be an acceptance
criteria. Beast is currently designed to be a part of Boost:
nothing more, nothing less. Looking at the bigger picture, it
is the author's goal to propose this library for standardization.
A logical track for achieving this is as follows:
[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
will logically accompany this process. There is a small benchmarking
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!"
@ -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
certificates would help."
][
The HTTP interface doesn't try to reinvent the wheel, it just uses
the `boost::asio::ip::tcp::socket` or `boost::asio::ssl::stream` that
you set up beforehand. Callers use the interfaces already existing
on those objects to make outgoing connections, accept incoming connections,
or establish TLS sessions with certificates. We find the available Asio
examples for performing these tasks sufficient.
The server-framework example demonstrates how to implement a server
that supports TLS using certificates. There are also websocket and
HTTP client examples which use TLS. Furthermore, management of
certificates is beyond the scope of the public interfaces of the
library. Asio already provides documentation, interfaces, and
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
in HTTP requests, and dispatch them to calling code. The authors feel
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?"
][
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
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
@ -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),
etc."
][
Beast does not provide direct facilities for implementing TLS connections;
however, the interfaces already existing on the `boost::asio::ssl::stream`
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.
Beast works with the Stream concept, so it automatically works with the
`boost::asio::ssl::stream` that you have already set up through Asio.
]]
[[
@ -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
cgi-gateway can be built.
One of the example programs implements a simple HTTP server that
delivers files from the filesystem.
There are several HTTP servers in the example directory which deliver
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."
][
The Beast interface supports this functionality (by allowing this
special case of "split" message parsing and serialization). Specifically,
it lets callers read the request up to just before the body,
and let callers write the request up to just before the body. However,
making use of this behavior is up to callers (since Beast is low level).
Deciding on whether to send the "Expect: 100-continue" header or
how to handle it on the server side is the caller's responsibility;
Beast provides the functionality to send or inspect the header before
sending or reading the body.
]]
@ -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
works in practice."
][
Beast.HTTP and Beast.WebSocket are production ready and currently
running on public servers receiving traffic and handling millions of
dollars' worth of financial transactions daily. The servers run [*rippled],
open source software ([@https://github.com/ripple/rippled repository])
Beast has already been on public servers receiving traffic and handling
hundreds of millions of dollars' worth of financial transactions daily.
The servers run [*rippled], open source software
([@https://github.com/ripple/rippled repository])
implementing the
[@https://ripple.com/files/ripple_consensus_whitepaper.pdf [*Ripple Consensus Protocol]],
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
interface on `ssl::stream` like shown in all of the Asio examples, then
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
interface paint on the `ssl::stream`.
Beast comes with an `ssl_stream` wrapper in the example directory which
allows the SSL stream to be moved, overcoming an Asio limitation.
The WebSocket implementation [*does] provide support for shutting down
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
websocket::stream<tcp::socket&> ws{sock};
// Perform the websocket handhskae
// Perform the websocket handshake
ws.handshake(host, "/", ec);
if(ec)
return fail("handshake", ec);

View File

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

View File

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