mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 21:34:46 +02:00
@@ -1,6 +1,7 @@
|
||||
Version 71:
|
||||
|
||||
* Fix extra ; warning
|
||||
* Documentation revision
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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`]
|
||||
|
@@ -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]]
|
||||
@@ -34,7 +34,7 @@ __message__ objects; user-defined parsers are also possible:
|
||||
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
|
||||
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>;
|
||||
```
|
||||
]]
|
||||
]
|
||||
|
@@ -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:
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
127
doc/9_4_faq.qbk
127
doc/9_4_faq.qbk
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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:
|
||||
|
@@ -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};
|
||||
|
||||
//]
|
||||
}
|
||||
|
Reference in New Issue
Block a user