mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
Update and tidy documentation
This commit is contained in:
@ -3,8 +3,9 @@
|
||||
* Add missing rebind to handler_alloc
|
||||
* Fix error handling in http server examples
|
||||
* Fix CMake scripts for MinGW
|
||||
* Better WebSocket decorator
|
||||
* Use BOOST_ASSERT
|
||||
* Better WebSocket decorator
|
||||
* Update and tidy documentation
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -15,15 +15,15 @@ using boostbook ;
|
||||
using quickbook ;
|
||||
using doxygen ;
|
||||
|
||||
xml beast_boostbook : master.qbk ;
|
||||
import quickbook ;
|
||||
|
||||
path-constant out : . ;
|
||||
path-constant here : . ;
|
||||
|
||||
install stylesheets
|
||||
:
|
||||
$(broot)/doc/src/boostbook.css
|
||||
:
|
||||
<location>$(out)/html
|
||||
<location>$(here)/html
|
||||
;
|
||||
|
||||
explicit stylesheets ;
|
||||
@ -35,7 +35,7 @@ install images
|
||||
images/body.png
|
||||
images/message.png
|
||||
:
|
||||
<location>$(out)/html/images
|
||||
<location>$(here)/html/images
|
||||
;
|
||||
|
||||
explicit images ;
|
||||
@ -44,40 +44,49 @@ install callouts
|
||||
:
|
||||
[ glob $(broot)/doc/src/images/callouts/*.png ]
|
||||
:
|
||||
<location>$(out)/html/images/callouts
|
||||
<location>$(here)/html/images/callouts
|
||||
;
|
||||
|
||||
explicit callout ;
|
||||
|
||||
boostbook doc
|
||||
install examples
|
||||
:
|
||||
beast_boostbook
|
||||
[ glob ../examples/*.* ]
|
||||
:
|
||||
<xsl:param>chapter.autolabel=0
|
||||
<xsl:param>boost.image.src=images/beast.png
|
||||
<xsl:param>boost.image.alt="Beast Logo"
|
||||
<xsl:param>boost.image.w=2400
|
||||
<xsl:param>boost.image.h=80
|
||||
<xsl:param>boost.root=$(broot)
|
||||
<xsl:param>chapter.autolabel=0
|
||||
<xsl:param>chunk.first.sections=1 # Chunk the first top-level section?
|
||||
<xsl:param>chunk.section.depth=8 # Depth to which sections should be chunked
|
||||
<xsl:param>generate.section.toc.level=1 # Control depth of TOC generation in sections
|
||||
<xsl:param>toc.max.depth=2 # How many levels should be created for each TOC?
|
||||
<xsl:param>toc.section.depth=2 # How deep should recursive sections appear in the TOC?
|
||||
:
|
||||
<location>temp
|
||||
<dependency>stylesheets
|
||||
<dependency>images
|
||||
<location>$(here)/html/examples
|
||||
;
|
||||
|
||||
#explicit doc ;
|
||||
# <xsl:param>nav.layout=none
|
||||
# <format>html:<xsl:param>location=../bin/doc/html
|
||||
# <xsl:param>generate.toc="chapter nop section nop"
|
||||
# <xsl:param>root.filename=index
|
||||
# <xsl:param>output-root="../bin/html"
|
||||
explicit examples ;
|
||||
|
||||
xml doc
|
||||
:
|
||||
master.qbk
|
||||
:
|
||||
<location>temp
|
||||
<include>$(broot)/tools/boostbook/dtd
|
||||
;
|
||||
|
||||
boostbook boostdoc
|
||||
:
|
||||
doc
|
||||
:
|
||||
<xsl:param>boost.root=$(broot)
|
||||
<xsl:param>boost.image.src=images/beast.png
|
||||
<xsl:param>boost.image.alt="Beast Logo"
|
||||
<xsl:param>boost.image.w=1330
|
||||
<xsl:param>boost.image.h=80
|
||||
<xsl:param>chapter.autolabel=0
|
||||
<xsl:param>chunk.section.depth=8 # Depth to which sections should be chunked
|
||||
<xsl:param>chunk.first.sections=1 # Chunk the first top-level section?
|
||||
<xsl:param>toc.section.depth=8 # How deep should recursive sections appear in the TOC?
|
||||
<xsl:param>toc.max.depth=8 # How many levels should be created for each TOC?
|
||||
<xsl:param>generate.section.toc.level=8 # Control depth of TOC generation in sections
|
||||
<xsl:param>generate.toc="chapter nop section nop"
|
||||
<include>$(broot)/tools/boostbook/dtd
|
||||
:
|
||||
<location>temp
|
||||
<dependency>examples
|
||||
<dependency>images
|
||||
<dependency>stylesheets
|
||||
;
|
||||
|
||||
#[include reference.qbk]
|
||||
#[xinclude index.xml]
|
@ -25,7 +25,7 @@ libraries:
|
||||
* Let library users make the important decisions such as how to
|
||||
allocate memory or how to leverage flow control.
|
||||
|
||||
Beast uses the [link beast.types.DynamicBuffer [*`DynamicBuffer`]] concept
|
||||
Beast uses the [link beast.ref.DynamicBuffer [*`DynamicBuffer`]] concept
|
||||
presented in the Netwoking TS, and relies heavily on the Boost.Asio
|
||||
[*`ConstBufferSequence`] and [*`MutableBufferSequence`] concepts for passing
|
||||
buffers to functions. The authors have found the dynamic buffer and buffer
|
||||
|
111
doc/examples.qbk
Normal file
111
doc/examples.qbk
Normal file
@ -0,0 +1,111 @@
|
||||
[/
|
||||
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:example Examples]
|
||||
|
||||
These usage examples are intended to quickly impress upon readers the
|
||||
flavor of the library. They are complete programs which may be built
|
||||
and run. Source code and build scripts for these programs may be found
|
||||
in the examples directory.
|
||||
|
||||
[heading HTTP GET]
|
||||
|
||||
Use HTTP to request the root page from a website and print the response:
|
||||
|
||||
```
|
||||
#include <beast/http.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "boost.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
|
||||
|
||||
// Send HTTP request using beast
|
||||
beast::http::request_v1<beast::http::empty_body> req;
|
||||
req.method = "GET";
|
||||
req.url = "/";
|
||||
req.version = 11;
|
||||
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
|
||||
req.headers.replace("User-Agent", "Beast");
|
||||
beast::http::prepare(req);
|
||||
beast::http::write(sock, req);
|
||||
|
||||
// Receive and print HTTP response using beast
|
||||
beast::streambuf sb;
|
||||
beast::http::response_v1<beast::http::streambuf_body> resp;
|
||||
beast::http::read(sock, sb, resp);
|
||||
std::cout << resp;
|
||||
}
|
||||
```
|
||||
[heading WebSocket]
|
||||
|
||||
Establish a WebSocket connection, send a message and receive the reply:
|
||||
```
|
||||
#include <beast/core/to_string.hpp>
|
||||
#include <beast/websocket.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "echo.websocket.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
|
||||
|
||||
// WebSocket connect and send message using beast
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
|
||||
ws.handshake(host, "/");
|
||||
ws.write(boost::asio::buffer("Hello, world!"));
|
||||
|
||||
// Receive WebSocket message, print and close using beast
|
||||
beast::streambuf sb;
|
||||
beast::websocket::opcode op;
|
||||
ws.read(op, sb);
|
||||
ws.close(beast::websocket::close_code::normal);
|
||||
std::cout << to_string(sb.data()) << "\n";
|
||||
}
|
||||
```
|
||||
|
||||
[heading HTTP Crawl]
|
||||
|
||||
This example retrieves the page at each of the most popular domains
|
||||
as measured by Alexa.
|
||||
|
||||
* [@examples/http_crawl.cpp]
|
||||
|
||||
[heading HTTP Server]
|
||||
|
||||
This example demonstrates both synchronous and asynchronous server
|
||||
implementations. It also provides an example of implementing a [*Body]
|
||||
type, in `file_body`.
|
||||
|
||||
* [@examples/file_body.hpp]
|
||||
* [@examples/http_async_server.hpp]
|
||||
* [@examples/http_sync_server.hpp]
|
||||
* [@examples/http_server.cpp]
|
||||
|
||||
[heading Listings]
|
||||
|
||||
These are stand-alone listings of the HTTP and WebSocket examples.
|
||||
|
||||
* [@examples/http_example.cpp]
|
||||
* [@examples/websocket_example.cpp]
|
||||
|
||||
[endsect]
|
401
doc/http.qbk
401
doc/http.qbk
@ -5,138 +5,149 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:http HTTP]
|
||||
|
||||
|
||||
[section:http Using HTTP]
|
||||
|
||||
[block '''
|
||||
<informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist>
|
||||
<member><link linkend="beast.http.message">Message</link></member>
|
||||
<member><link linkend="beast.http.headers">Headers</link></member>
|
||||
<member><link linkend="beast.http.body">Body</link></member>
|
||||
<member><link linkend="beast.http.algorithms">Algorithms</link></member>
|
||||
<member><link linkend="beast.http.sockets">Sockets</link></member>
|
||||
</simplelist></entry></row></tbody></tgroup></informaltable>
|
||||
''']
|
||||
|
||||
Beast.HTTP offers programmers simple and performant models of HTTP messages and
|
||||
their associated operations including synchronous and asynchronous reading and
|
||||
writing of messages in the HTTP/1 wire format using Boost.Asio.
|
||||
|
||||
The HTTP protocol is described fully in
|
||||
[@https://tools.ietf.org/html/rfc7230 rfc7230]
|
||||
|
||||
|
||||
|
||||
[section:motivation Motivation]
|
||||
|
||||
The HTTP protocol is pervasive in network applications. As C++ is a logical
|
||||
choice for high performance network servers, there is great utility in solid
|
||||
building blocks for manipulating, sending, and receiving HTTP messages
|
||||
compliant with the Hypertext Transfer Protocol and the supplements that
|
||||
follow. Unfortunately reliable implementations or industry standards do not
|
||||
exist in C++.
|
||||
|
||||
Beast.HTTP is built on Boost.Asio and uses its own robust header-only HTTP/1
|
||||
message parser modeled after the nodejs http-parser (written in C). A proposal
|
||||
to add networking functionality to the C++ standard library, based on
|
||||
Boost.Asio, is under consideration by the standards committee. Since the final
|
||||
approved networking interface for the C++ standard library will likely closely
|
||||
resemble the current interface of Boost.Asio, it is logical for Beast.HTTP to
|
||||
use Boost.Asio as its network transport.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:scope Scope]
|
||||
|
||||
This library is designed to be a building block for creating higher level
|
||||
libraries. It is not designed to be end-user facing. There is no convenient
|
||||
class that implements the core of a web server, nor is there a convenient
|
||||
class to quickly perform common operations such as fetching a file or
|
||||
connecting and retrieving a document from a secure connection. These
|
||||
use-cases are important, but this library does not try to do that. Instead,
|
||||
it offers primitives that can be used to build those user-facing algorithms.
|
||||
|
||||
A HTTP message (referred to hereafter as "message") contains request or
|
||||
response specific attributes, a series of zero or more name/value pairs
|
||||
(collectively termed "headers"), and a series of octets called the message
|
||||
body which may be zero in length. The HTTP protocol defines the client and
|
||||
server roles: clients send messages called requests and servers send back
|
||||
messages called responses. `http::message` models both requests and responses.
|
||||
Beast aims to offer this functionality:
|
||||
|
||||
* [*Model]: Provide a universal HTTP message class model.
|
||||
|
||||
* [*Build]: Construct a new message and manipulate its contents.
|
||||
|
||||
* [*Parse]: Deserialize a message from a network or memory stream in HTTP/1 wire format.
|
||||
|
||||
* [*Serialize]: Serialize a message into a network or memory stream in HTTP/1 wire format.
|
||||
|
||||
[note The documentation which follows assumes familiarity with
|
||||
both Boost.Asio and the HTTP protocol specification described in
|
||||
[@https://tools.ietf.org/html/rfc7230 rfc7230] ]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:usage Usage]
|
||||
messages called responses.
|
||||
|
||||
[note
|
||||
Sample code and identifiers mentioned in this section are written
|
||||
as if the following declarations are in effect:
|
||||
The following documentation assumes familiarity with both Boost.Asio
|
||||
and the HTTP protocol specification described in __rfc7230__. Sample code
|
||||
and identifiers mentioned in this section are written as if the following
|
||||
declarations are in effect:
|
||||
```
|
||||
#include <beast/http.hpp>
|
||||
using namespace beast;
|
||||
using namespace beast::http;
|
||||
```
|
||||
]
|
||||
|
||||
|
||||
|
||||
In the paragraphs that follow we describe the available interfaces for
|
||||
performing typical operations such as interacting with a HTTP server
|
||||
or handling simple requests. Subsequent sections cover the message model
|
||||
and its customization points in more depth, for advanced applications.
|
||||
[section:message Message]
|
||||
|
||||
[heading Declarations]
|
||||
The __message__ class template models HTTP/2 requests and responses, while the
|
||||
derived class __message_v1__ models HTTP/1 requests and responses, adding the
|
||||
required version field. These objects are complete: they contain
|
||||
all the information required to permit the algorithms to operate. These objects
|
||||
are first class: They may be returned from functions, moved, copied, passed
|
||||
as arguments, and stored in containers. Request and response messages are
|
||||
distinct types; functions may be overloaded on just one or the other if
|
||||
desired. Because this class template supports HTTP/1 and HTTP/2, it is
|
||||
sometimes referred to as the universal message model.
|
||||
|
||||
To do anything, a message must be declared. The message class template
|
||||
requires at minimum, a value indicating whether the message is a request
|
||||
(versus a response), and a `Body` type. The choice of `Body` determines the
|
||||
kind of container used to represent the message body. Here we will
|
||||
declare a HTTP/1 request that has a `std::string` for the body container:
|
||||
These class templates have three template parameters:
|
||||
```
|
||||
http::message_v1<true, http::string_body> req;
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
class message;
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
class message_v1;
|
||||
```
|
||||
|
||||
Two type aliases are provided for notational convenience when declaring
|
||||
HTTP/1 messages. These two statements declare a request and a response
|
||||
respectively:
|
||||
* [*`isRequest`]: Controls whether or not the message is a request or response.
|
||||
Depending on the value, different data members will be present in the resulting
|
||||
type.
|
||||
|
||||
* [*`Body`]: determines both the kind of container used to represent the
|
||||
message body and the algorithms used to parse and serialize it.
|
||||
|
||||
* [*`Headers`]: determines the container used to represent the HTTP headers.
|
||||
|
||||
For notational convenience, the following template type aliases are provided:
|
||||
```
|
||||
http::request_v1<http::string_body> req;
|
||||
http::response_v1<http::string_body> resp;
|
||||
template<class Body, class Headers = basic_headers<std::allocator<char>>>
|
||||
using request = message<true, Body, Headers>;
|
||||
|
||||
template<class Body, class Headers = basic_headers<std::allocator<char>>>
|
||||
using response = message<false, Body, Headers>;
|
||||
|
||||
template<class Body, class Headers = basic_headers<std::allocator<char>>>
|
||||
using request_v1 = message_v1<true, Body, Headers>;
|
||||
|
||||
template<class Body, class Headers = basic_headers<std::allocator<char>>>
|
||||
using response_v1 = message_v1<false, Body, Headers>;
|
||||
```
|
||||
|
||||
[heading Members]
|
||||
Although these aliases have a common base class, they have different fields
|
||||
depending on whether the message is a request or a response. These simplified
|
||||
declarations notionally illustrate the members of HTTP/1 messages:
|
||||
|
||||
Message objects are default constructible, with public access to data members.
|
||||
Request and response objects have some common members, and some members unique
|
||||
to the message type. These statements set all the members in each message:
|
||||
```
|
||||
http::request_v1<http::string_body> req;
|
||||
template<class Body, class Headers>
|
||||
struct request_v1
|
||||
{
|
||||
int version; 10 or 11
|
||||
std::string method;
|
||||
std::string url;
|
||||
Headers headers;
|
||||
typename Body::value_type body;
|
||||
};
|
||||
|
||||
template<class Body, class Headers>
|
||||
struct response_v1
|
||||
{
|
||||
int version; 10 or 11
|
||||
int status;
|
||||
std::string reason;
|
||||
Headers headers;
|
||||
typename Body::value_type body;
|
||||
};
|
||||
```
|
||||
|
||||
These statements set fields in request and response message objects:
|
||||
```
|
||||
request_v1<string_body> req;
|
||||
req.method = "GET";
|
||||
req.url = "/index.html";
|
||||
req.version = 11; // HTTP/1.1
|
||||
req.headers.insert("User-Agent", "hello_world");
|
||||
req.headers.insert("User-Agent", "Beast.HTTP");
|
||||
req.body = "";
|
||||
|
||||
http::response_v1<http::string_body> resp;
|
||||
resp.status = 404;
|
||||
resp.reason = "Not Found";
|
||||
resp.version = 10; // HTTP/1.0
|
||||
resp.headers.insert("Server", "Beast.HTTP");
|
||||
resp.body = "The requested resource was not found.";
|
||||
response_v1<string_body> res;
|
||||
res.status = 404;
|
||||
res.reason = "Not Found";
|
||||
res.version = 10; // HTTP/1.0
|
||||
res.headers.insert("Server", "Beast.HTTP");
|
||||
res.body = "The requested resource was not found.";
|
||||
```
|
||||
|
||||
[heading Headers]
|
||||
[endsect]
|
||||
|
||||
The `message::headers` member is a container for setting the field/value
|
||||
pairs in the message. These statements change the values of the headers
|
||||
in the message passed:
|
||||
|
||||
|
||||
[section:headers Headers]
|
||||
|
||||
The [*`Headers`] type represents a container that can set or retrieve the
|
||||
headers in a message. Beast provides the
|
||||
[link beast.ref.http__basic_headers `basic_headers`] class which serves
|
||||
the needs for most users. It supports modification and inspection of values.
|
||||
The field names are not case-sensitive.
|
||||
|
||||
These statements change the values of the headers in the message passed:
|
||||
```
|
||||
template<class Body>
|
||||
void set_fields(http::request_v1<Body>& req)
|
||||
void set_fields(request_v1<Body>& req)
|
||||
{
|
||||
if(! req.exists("User-Agent"))
|
||||
req.insert("User-Agent", "myWebClient");
|
||||
@ -148,17 +159,32 @@ in the message passed:
|
||||
}
|
||||
```
|
||||
|
||||
[heading Body]
|
||||
[heading Advanced]
|
||||
|
||||
The `message::body` member represents the message body. Depending on the
|
||||
`Body` template argument type, this could be a writable container. The
|
||||
following types, provided by the library, are suitable choices for the
|
||||
`Body` type:
|
||||
This illustration shows more detail about the
|
||||
[link beast.ref.http__message [*`message`]] class template (boilerplate
|
||||
present in the actual declaration has been removed for clarity):
|
||||
|
||||
[$images/message.png [width 580px] [height 225px]]
|
||||
|
||||
User defined [*`Headers`] types are possible. To support serialization, the
|
||||
type must meet the requirements of __FieldSequence__. To support parsing using
|
||||
the provided parser, the type must provide the `insert` member function.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:body Body]
|
||||
|
||||
The message [*`Body`] template parameter controls both the type of the data
|
||||
member of the resulting message object, and the algorithms used during parsing
|
||||
and serialization. Beast provides three very common [*`Body`] types:
|
||||
|
||||
* [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body.
|
||||
Used in GET requests where there is no message body. Example:
|
||||
```
|
||||
http::request_v1<http::empty_body> req;
|
||||
request_v1<empty_body> req;
|
||||
req.version = 11;
|
||||
req.method = "GET";
|
||||
req.url = "/index.html";
|
||||
@ -170,36 +196,83 @@ or response with simple text in the message body (such as an error message).
|
||||
Has the same insertion complexity of `std::string`. This is the type of body
|
||||
used in the examples:
|
||||
```
|
||||
http::response_v1<http::string_body> resp;
|
||||
static_assert(std::is_same<decltype(resp.body), std::string>::value);
|
||||
resp.body = "Here is the data you requested";
|
||||
response_v1<string_body> res;
|
||||
static_assert(std::is_same<decltype(res.body), std::string>::value);
|
||||
res.body = "Here is the data you requested";
|
||||
```
|
||||
|
||||
* [link beast.ref.http__streambuf_body [*`streambuf_body`:]] A body with a
|
||||
`value_type` of [link beast.ref.streambuf `streambuf`]: an efficient storage
|
||||
object which uses multiple octet arrays of varying lengths to represent data.
|
||||
|
||||
[heading Sockets]
|
||||
[heading Advanced]
|
||||
|
||||
User-defined types are possible for the message body, where the type meets the
|
||||
[link beast.ref.Body [*`Body`]] requirements. This simplified class declaration
|
||||
shows the customization points available to user-defined body types:
|
||||
|
||||
[$images/body.png [width 510px] [height 210px]]
|
||||
|
||||
* [*`value_type`]: Determines the type of the
|
||||
[link beast.ref.http__message.body `message::body`] member. If this
|
||||
type defines default construction, move, copy, or swap, then message objects
|
||||
declared with this [*`Body`] will have those operations defined.
|
||||
|
||||
* [*`reader`]: An optional nested type meeting the requirements of
|
||||
[link beast.ref.Reader [*`Reader`]]. If present, this defines the algorithm
|
||||
used for parsing bodies of this type.
|
||||
|
||||
* [*`writer`]: An optional nested type meeting the requirements of
|
||||
[link beast.ref.Writer [*`Writer`]]. If present, this defines the algorithm
|
||||
used for serializing bodies of this type.
|
||||
|
||||
The examples included with this library provide a Body implementation that
|
||||
serializing message bodies that come from a file.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:algorithms Algorithms]
|
||||
|
||||
In addition to the universal message model, Beast provides synchronous
|
||||
algorithms which operate on HTTP/1 messages:
|
||||
|
||||
* [link beast.ref.http__read [*read]]: Parse a message from a stream
|
||||
|
||||
* [link beast.ref.http__write [*write]]: Serialize a message into its wire format on a stream
|
||||
|
||||
Asynchronous versions of these algorithms are also available:
|
||||
|
||||
* [link beast.ref.http__async_read [*async_read]]: Parse a message from a stream
|
||||
|
||||
* [link beast.ref.http__async_write [*async_write]]: Serialize a message into its wire format on a stream
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:sockets Using Sockets]
|
||||
|
||||
The library provides simple free functions modeled after Boost.Asio to
|
||||
send and receive messages on TCP/IP sockets, SSL streams, or any object
|
||||
which meets the Boost.Asio type requirements (SyncReadStream, SyncWriteStream,
|
||||
AsyncReadStream, and AsyncWriteStream depending on the types of operations
|
||||
performed). To send messages synchronously, use one of the `http:write`
|
||||
functions:
|
||||
performed). To send messages synchronously, use one of the
|
||||
[link beast.ref.http__write `write`] functions:
|
||||
```
|
||||
void send_request(boost::asio::ip::tcp::socket& sock)
|
||||
{
|
||||
http::request<http::empty_body> req;
|
||||
request<empty_body> req;
|
||||
req.version = 11;
|
||||
req.method = "GET";
|
||||
req.url = "/index.html";
|
||||
...
|
||||
http::write(sock, req); // Throws exception on error
|
||||
write(sock, req); // Throws exception on error
|
||||
...
|
||||
// Alternatively
|
||||
boost::system::error:code ec;
|
||||
http::write(sock, req, ec);
|
||||
write(sock, req, ec);
|
||||
if(ec)
|
||||
std::cerr << "error writing http message: " << ec.message();
|
||||
}
|
||||
@ -209,27 +282,27 @@ An asynchronous interface is available:
|
||||
```
|
||||
void handle_write(boost::system::error_code);
|
||||
...
|
||||
http::request_v1<http::empty_body> req;
|
||||
request_v1<empty_body> req;
|
||||
...
|
||||
http::async_write(sock, req, std::bind(&handle_write, std::placeholders::_1));
|
||||
async_write(sock, req, std::bind(&handle_write, std::placeholders::_1));
|
||||
```
|
||||
|
||||
When the implementation reads messages from a socket, it can read bytes lying
|
||||
after the end of the message if they are present (the alternative is to read
|
||||
a single byte at a time which is unsuitable for performance reasons). To
|
||||
store and re-use these extra bytes on subsequent messages, the read interface
|
||||
requires an additional parameter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]]
|
||||
requires an additional parameter: a [link beast.ref.DynamicBuffer [*`DynamicBuffer`]]
|
||||
object. This example reads a message from the socket, with the extra bytes
|
||||
stored in the streambuf parameter for use in a subsequent call to read:
|
||||
```
|
||||
boost::asio::streambuf sb;
|
||||
...
|
||||
http::response_v1<http::string_body> resp;
|
||||
http::read(sock, sb, resp); // Throws exception on error
|
||||
response_v1<string_body> res;
|
||||
read(sock, sb, res); // Throws exception on error
|
||||
...
|
||||
// Alternatively
|
||||
boost::system::error:code ec;
|
||||
http::read(sock, sb, resp, ec);
|
||||
read(sock, sb, res, ec);
|
||||
if(ec)
|
||||
std::cerr << "error reading http message: " << ec.message();
|
||||
```
|
||||
@ -241,116 +314,28 @@ called:
|
||||
void handle_read(boost::system::error_code);
|
||||
...
|
||||
boost::asio::streambuf sb;
|
||||
http::response_v1<http::string_body> resp;
|
||||
response_v1<string_body> res;
|
||||
...
|
||||
http::async_read(sock, resp, std::bind(&handle_read, std::placeholders::_1));
|
||||
async_read(sock, res, std::bind(&handle_read, std::placeholders::_1));
|
||||
```
|
||||
|
||||
An alternative to using a `boost::asio::streambuf` is to use a
|
||||
[link beast.ref.streambuf `beast::streambuf`], which meets the requirements of
|
||||
[*`DynamicBuffer`] and is optimized for performance:
|
||||
__streambuf__, which meets the requirements of __DynamicBuffer__ and
|
||||
is optimized for performance:
|
||||
```
|
||||
void handle_read(boost::system::error_code);
|
||||
...
|
||||
beast::streambuf sb;
|
||||
http::response_v1<http::string_body> resp;
|
||||
http::read(sock, sb, resp);
|
||||
response_v1<string_body> res;
|
||||
read(sock, sb, res);
|
||||
```
|
||||
|
||||
The `read` implementation can use any object meeting the requirements of
|
||||
[link beast.types.DynamicBuffer [*`DynamicBuffer`]], allowing callers to define custom
|
||||
__DynamicBuffer__, allowing callers to define custom
|
||||
memory management strategies used by the implementation.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:advanced Advanced]
|
||||
|
||||
The spectrum of hardware and software platforms which perform these typical
|
||||
HTTP operations is vast, ranging from powerful servers in large datacenters
|
||||
to tiny resource-limited embedded devices. No single concrete implementation
|
||||
of a class intended to model messages can efficiently serve all needs.
|
||||
For example, an object that minimizes resources during parsing may not be
|
||||
able to edit and change headers dynamically. A message that represents the
|
||||
message body as a disk file may support sending but not parsing. Many efficient
|
||||
and correct models of messages exist, supporting some or all of the
|
||||
operations listed above.
|
||||
|
||||
[heading Message model]
|
||||
|
||||
The message class template and provided Body types are suitable for casual
|
||||
library users. This section explains the message model for advanced users
|
||||
who wish to take control over aspects of the implementation. We introduce
|
||||
customization points for the header and body via class template arguments.
|
||||
This illustration shows more detail about the
|
||||
[link beast.ref.http__message [*`message`]] class template (boilerplate
|
||||
present in the actual declaration has been removed for clarity):
|
||||
|
||||
[$images/message.png [width 580px] [height 225px]]
|
||||
|
||||
The default constructor, move special members, and copy special members are
|
||||
all defaulted. A message is movable, copyable, or default constructible based
|
||||
on the capabilities of its template arguments.
|
||||
|
||||
Messages modeled in this fashion are ['complete], containing all of the
|
||||
information required to perform the supported set of operations. They are
|
||||
['first-class types], returnable from functions and composable. HTTP
|
||||
requests and responses are distinct types, allowing functions to be
|
||||
overloaded on the type of message.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:headers Headers Type]
|
||||
|
||||
The `Headers` type represents the field/value pairs present in every HTTP
|
||||
message. These types implement the
|
||||
[link beast.types.FieldSequence [*`FieldSequence`]]
|
||||
concept. The value type of a field sequence is an object meeting the
|
||||
requirements of [link beast.types.Field [*`Field`]]. The implementation can
|
||||
serialize any instance of `Headers` that meets the field sequence requirements.
|
||||
This example shows a function which returns `true` if the specified field
|
||||
sequence has a connect field:
|
||||
```
|
||||
template<class FieldSequence>
|
||||
bool
|
||||
has_connect(FieldSequence const& fs)
|
||||
{
|
||||
return std::find_if(fs.begin(), fs.end(),
|
||||
[&](auto const& field)
|
||||
{
|
||||
return ci_equal(field.name(), "Connect");
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:body Body Type]
|
||||
|
||||
The `Body` template argument in the `message` class must meet the
|
||||
[link beast.types.Body [*`Body`] requirements]. It provides customization
|
||||
of the data member in the message, the algorithm for parsing, and the
|
||||
algorithm for serialization:
|
||||
|
||||
[$images/body.png [width 510px] [height 210px]]
|
||||
|
||||
Instances of the optional nested types `writer` and `reader` perform
|
||||
serialization and deserialization of the message body. If either or
|
||||
both of these types are present, the message becomes serializable, parsable,
|
||||
or both. They model [link beast.types.Reader [*`Reader`]] and
|
||||
[link beast.types.Writer [*`Writer`]] respectively.
|
||||
|
||||
For specialized applications, users may implement their own types which
|
||||
meet the requirements. The examples included with this library provide a
|
||||
Body implementation used to serve files in a HTTP server.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 145 KiB |
@ -8,6 +8,7 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
|
||||
<section id="index">
|
||||
<section id="beast.index">
|
||||
<title>Index</title>
|
||||
<index/>
|
||||
</section>
|
||||
|
233
doc/master.qbk
233
doc/master.qbk
@ -8,7 +8,7 @@
|
||||
[library Beast
|
||||
[quickbook 1.6]
|
||||
[copyright 2013 - 2016 Vinnie Falco]
|
||||
[purpose C++ Library]
|
||||
[purpose Networking Protocol Library]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -22,174 +22,75 @@
|
||||
[template mdash[] '''— ''']
|
||||
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
|
||||
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
|
||||
[def __POSIX__ /POSIX/]
|
||||
[def __Windows__ /Windows/]
|
||||
[def __accept__ [@http://www.opengroup.org/onlinepubs/000095399/functions/accept.html `accept()`]]
|
||||
[def __connect__ [@http://www.opengroup.org/onlinepubs/000095399/functions/connect.html `connect()`]]
|
||||
[def __getpeername__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getpeername.html `getpeername()`]]
|
||||
[def __getsockname__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getsockname.html `getsockname()`]]
|
||||
[def __getsockopt__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getsockopt.html `getsockopt()`]]
|
||||
[def __ioctl__ [@http://www.opengroup.org/onlinepubs/000095399/functions/ioctl.html `ioctl()`]]
|
||||
[def __recvfrom__ [@http://www.opengroup.org/onlinepubs/000095399/functions/recvfrom.html `recvfrom()`]]
|
||||
[def __sendto__ [@http://www.opengroup.org/onlinepubs/000095399/functions/sendto.html `sendto()`]]
|
||||
[def __setsockopt__ [@http://www.opengroup.org/onlinepubs/000095399/functions/setsockopt.html `setsockopt()`]]
|
||||
[def __socket__ [@http://www.opengroup.org/onlinepubs/000095399/functions/socket.html `socket()`]]
|
||||
|
||||
[def __asio_handler_invoke__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]]
|
||||
[def __asio_handler_allocate__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]]
|
||||
[def __AsyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]]
|
||||
[def __AsyncWriteStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]]
|
||||
[def __Body__ [link beast.ref.Body [*`Body`]]]
|
||||
[def __CompletionHandler__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]]
|
||||
[def __ConstBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*`ConstBufferSequence`]]]
|
||||
[def __DynamicBuffer__ [link beast.ref.DynamicBuffer [*`DynamicBuffer`]]]
|
||||
[def __FieldSequence__ [link beast.ref.FieldSequence [*`FieldSequence`]]]
|
||||
[def __message__ [link beast.ref.http__message `message`]]
|
||||
[def __message_v1__ [link beast.ref.http__message_v1 `message_v1`]]
|
||||
[def __MutableBufferSequence [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]]
|
||||
[def __rfc6455__ [@https://tools.ietf.org/html/rfc6455 rfc6455]]
|
||||
[def __rfc7230__ [@https://tools.ietf.org/html/rfc7230 rfc7230]]
|
||||
[def __streambuf__ [link beast.ref.streambuf `streambuf`]]
|
||||
[def __SyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]]
|
||||
[def __SyncWriteStream__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]]
|
||||
[def __void_or_deduced__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]]
|
||||
|
||||
Beast is a cross-platform, header-only C++ library built on Boost.Asio that
|
||||
provides implementations of the HTTP and WebSocket protocols.
|
||||
|
||||
[section:intro Introduction]
|
||||
|
||||
Beast is a header-only, cross-platform C++ library built on Boost.Asio and
|
||||
Boost, containing two modules implementing widely used network protocols.
|
||||
Beast.HTTP offers a universal model for describing, sending, and receiving
|
||||
HTTP messages while Beast.WebSocket provides a complete implementation of
|
||||
the WebSocket protocol. Their design achieves these goals:
|
||||
|
||||
* [*Symmetry.] Interfaces are role-agnostic; the same interfaces can be
|
||||
used to build clients, servers, or both.
|
||||
|
||||
* [*Ease of Use.] HTTP messages are modeled using simple, readily
|
||||
accessible objects. Functions and classes used to send and receive HTTP
|
||||
or WebSocket messages are designed to resemble Boost.Asio as closely as
|
||||
possible. Users familiar with Boost.Asio will be immediately comfortable
|
||||
using this library.
|
||||
|
||||
* [*Flexibility.] Interfaces do not mandate specific implementation
|
||||
strategies; important decisions such as buffer or thread management are
|
||||
left to users of the library.
|
||||
|
||||
* [*Performance.] The implementation performs competitively, making it a
|
||||
realistic choice for building high performance network servers.
|
||||
|
||||
* [*Scalability.] Development of network applications that scale to thousands
|
||||
of concurrent connections is possible with the implementation.
|
||||
|
||||
* [*Basis for further abstraction.] The interfaces facilitate the
|
||||
development of other libraries that provide higher levels of abstraction.
|
||||
|
||||
|
||||
|
||||
[section:requirements Requirements]
|
||||
|
||||
Beast requires:
|
||||
|
||||
* [*C++11.] A minimum of C++11 is needed.
|
||||
* [*Boost.] Beast is built on Boost, especially Boost.Asio.
|
||||
* [*OpenSSL.] If using TLS/Secure sockets (optional).
|
||||
|
||||
[note Tested compilers: msvc-14+, gcc 5+, clang 3.6+]
|
||||
|
||||
The library is [*header-only]. It is not necessary to add any .cpp files,
|
||||
or to edit your existing build script or project file except to provide
|
||||
that the include/ directory for beast is searched for include files.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:example Examples]
|
||||
|
||||
These usage examples are intended to quickly impress upon readers the
|
||||
flavor of the library. They are complete programs which may be built
|
||||
and run. Source code and build scripts for these programs may be found
|
||||
in the examples directory.
|
||||
|
||||
Use HTTP to request the root page from a website and print the response:
|
||||
```
|
||||
#include <beast/http.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "boost.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
|
||||
|
||||
// Send HTTP request using beast
|
||||
beast::http::request_v1<beast::http::empty_body> req;
|
||||
req.method = "GET";
|
||||
req.url = "/";
|
||||
req.version = 11;
|
||||
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
|
||||
req.headers.replace("User-Agent", "Beast");
|
||||
beast::http::prepare(req);
|
||||
beast::http::write(sock, req);
|
||||
|
||||
// Receive and print HTTP response using beast
|
||||
beast::streambuf sb;
|
||||
beast::http::response_v1<beast::http::streambuf_body> resp;
|
||||
beast::http::read(sock, sb, resp);
|
||||
std::cout << resp;
|
||||
}
|
||||
```
|
||||
|
||||
Establish a WebSocket connection, send a message and receive the reply:
|
||||
```
|
||||
#include <beast/core/to_string.hpp>
|
||||
#include <beast/websocket.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Normal boost::asio setup
|
||||
std::string const host = "echo.websocket.org";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
boost::asio::ip::tcp::socket sock{ios};
|
||||
boost::asio::connect(sock,
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
|
||||
|
||||
// WebSocket connect and send message using beast
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
|
||||
ws.handshake(host, "/");
|
||||
ws.write(boost::asio::buffer("Hello, world!"));
|
||||
|
||||
// Receive WebSocket message, print and close using beast
|
||||
beast::streambuf sb;
|
||||
beast::websocket::opcode op;
|
||||
ws.read(op, sb);
|
||||
ws.close(beast::websocket::close_code::normal);
|
||||
std::cout << to_string(sb.data()) << "\n";
|
||||
}
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:credits Credits]
|
||||
|
||||
Boost.Asio is the inspiration behind which all of the interfaces and
|
||||
implementation strategies are built. Some parts of the documentation are
|
||||
written to closely resemble the wording and presentation of Boost.Asio
|
||||
documentation. Credit goes to Christopher Kohloff for the wonderful
|
||||
Asio library and the ideas upon which Beast is built.
|
||||
|
||||
Beast would not be possible without the considerable time and patience
|
||||
contributed by David Schwartz, Edward Hennis, Howard Hinnant, Miguel Portilla,
|
||||
Nikolaos Bougalis, Scott Determan, Scott Schurr, and Ripple Labs for
|
||||
supporting its development.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[variablelist
|
||||
[[
|
||||
[link beast.overview Overview]
|
||||
][
|
||||
An overview of features, requirements, and credits, plus
|
||||
rationale and design information.
|
||||
]]
|
||||
[[
|
||||
[link beast.http Using HTTP]
|
||||
][
|
||||
How to use Beast's HTTP interfaces in your applications.
|
||||
]]
|
||||
[[
|
||||
[link beast.websocket Using WebSocket]
|
||||
][
|
||||
How to use Beast's WebSocket interfaces in your applications.
|
||||
]]
|
||||
[[
|
||||
[link beast.example Examples]
|
||||
][
|
||||
Examples that illustrate the use of Beast in more complex applications.
|
||||
]]
|
||||
[[
|
||||
[link beast.quickref Reference]
|
||||
][
|
||||
Detailed class and function reference.
|
||||
]]
|
||||
[[
|
||||
[link beast.index Index]
|
||||
][
|
||||
Book-style text index of Beast documentation.
|
||||
]]
|
||||
]
|
||||
|
||||
[include overview.qbk]
|
||||
[include http.qbk]
|
||||
[include websocket.qbk]
|
||||
[include examples.qbk]
|
||||
|
||||
[section:types Type Requirements]
|
||||
[include design.qbk]
|
||||
|
||||
[section:quickref Reference]
|
||||
[xinclude quickref.xml]
|
||||
[endsect]
|
||||
|
||||
[section:ref Reference]
|
||||
[include types/Body.qbk]
|
||||
[include types/BufferSequence.qbk]
|
||||
[include types/DynamicBuffer.qbk]
|
||||
@ -199,13 +100,7 @@ supporting its development.
|
||||
[include types/Reader.qbk]
|
||||
[include types/Streams.qbk]
|
||||
[include types/Writer.qbk]
|
||||
[include reference.qbk]
|
||||
[endsect]
|
||||
|
||||
[include design.qbk]
|
||||
[section:quickref Quick Reference]
|
||||
[xinclude quickref.xml]
|
||||
[endsect]
|
||||
[include reference.qbk]
|
||||
[section:idx Index]
|
||||
[xinclude index.xml]
|
||||
[endsect]
|
||||
|
114
doc/overview.qbk
Normal file
114
doc/overview.qbk
Normal file
@ -0,0 +1,114 @@
|
||||
[/
|
||||
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:overview Introduction]
|
||||
|
||||
Beast is a header-only, cross-platform C++ library built on Boost.Asio and
|
||||
parts of Boost, containing two modules implementing widely used network
|
||||
protocols. Beast offers a universal HTTP message model, plus algorithms for
|
||||
parsing and serializing HTTP/1 messages. Beast.WebSocket provides a complete
|
||||
implementation of the WebSocket protocol. Their design achieves these goals:
|
||||
|
||||
* [*Symmetry.] Interfaces are role-agnostic; the same interfaces can be
|
||||
used to build clients, servers, or both.
|
||||
|
||||
* [*Ease of Use.] HTTP messages are modeled using simple, readily
|
||||
accessible objects. Functions and classes used to send and receive HTTP
|
||||
or WebSocket messages are designed to resemble Boost.Asio as closely as
|
||||
possible. Users familiar with Boost.Asio will be immediately comfortable
|
||||
using this library.
|
||||
|
||||
* [*Flexibility.] Interfaces do not mandate specific implementation
|
||||
strategies; important decisions such as buffer or thread management are
|
||||
left to users of the library.
|
||||
|
||||
* [*Performance.] The implementation performs competitively, making it a
|
||||
realistic choice for building high performance network servers.
|
||||
|
||||
* [*Scalability.] Development of network applications that scale to thousands
|
||||
of concurrent connections is possible with the implementation.
|
||||
|
||||
* [*Basis for further abstraction.] The interfaces facilitate the
|
||||
development of other libraries that provide higher levels of abstraction.
|
||||
|
||||
The HTTP portion of Beast is designed to be a low-level building block for
|
||||
creating higher level libraries. It implements only the HTTP protocol, and
|
||||
does not handle domain specific features (for example: cookies, redirects, or
|
||||
deflate content encodings).
|
||||
|
||||
[heading Requirements]
|
||||
|
||||
Beast requires:
|
||||
|
||||
* [*C++11.] A minimum of C++11 is needed.
|
||||
* [*Boost.] Beast is built on Boost, especially Boost.Asio.
|
||||
* [*OpenSSL.] If using TLS/Secure sockets (optional).
|
||||
|
||||
[note Tested compilers: msvc-14+, gcc 5+, clang 3.6+]
|
||||
|
||||
The library is [*header-only]. It is not necessary to add any .cpp files,
|
||||
or to add commands to your build script for building Beast. To link your
|
||||
program successfully, you'll need to add the Boost.System library to link
|
||||
with. If you use coroutines you'll also need the Boost.Coroutine library.
|
||||
Please visit the Boost documentation for instructions on how to do this for
|
||||
your particular build system.
|
||||
|
||||
[heading Motivation]
|
||||
|
||||
Beast is built on Boost.Asio A proposal to add networking functionality to the
|
||||
C++ standard library, based on Boost.Asio, is under consideration by the
|
||||
committee and on track for standardization. Since the final approved networking
|
||||
interface for the C++ standard library will likely closely resemble the current
|
||||
interface of Boost.Asio, the choice of Boost.Asio as the network transport
|
||||
layer is prudent.
|
||||
|
||||
The HTTP protocol is pervasive in network applications. As C++ is a logical
|
||||
choice for high performance network servers, there is great utility in solid
|
||||
building blocks for manipulating, sending, and receiving HTTP messages
|
||||
compliant with the Hypertext Transfer Protocol and the supplements that
|
||||
follow. Unfortunately reliable implementations or industry standards do not
|
||||
exist in C++. The development of higher level libraries is stymied by the
|
||||
lack of a common set of low-level algorithms and types for interacting with
|
||||
the HTTP protocol.
|
||||
|
||||
Today's web applications increasingly rely on alternatives to standard HTTP
|
||||
to achieve performance and/or responsiveness. While WebSocket implementations
|
||||
are widely available in common web development languages such as Javascript,
|
||||
good implementations in C++ are scarce. A survey of existing C++ WebSocket
|
||||
solutions reveals interfaces which lack symmetry, impose performance penalties,
|
||||
and needlessly restrict implementation strategies.
|
||||
|
||||
Beast.WebSocket takes advantage of Boost.Asio's extensible asynchronous
|
||||
model, handler allocation, and handler invocation hooks. Calls to
|
||||
Beast.WebSocket asynchronous initiation functions allow callers the choice
|
||||
of using a completion handler, stackful or stackless coroutines, futures,
|
||||
or user defined customizations (for example, Boost.Fiber). The
|
||||
implementation uses handler invocation hooks (__asio_handler_invoke__),
|
||||
providing execution guarantees on composed operations in a manner identical
|
||||
to Boost.Asio. The implementation also uses handler allocation hooks
|
||||
(__asio_handler_allocate__) when allocating memory internally for composed
|
||||
operations.
|
||||
|
||||
There is no need for inheritance or virtual members in a
|
||||
[link beast.ref.websocket__stream `websocket::stream`].
|
||||
All operations are templated and transparent to the compiler, allowing for
|
||||
maximum inlining and optimization.
|
||||
|
||||
[heading Credits]
|
||||
|
||||
Boost.Asio is the inspiration behind which all of the interfaces and
|
||||
implementation strategies are built. Some parts of the documentation are
|
||||
written to closely resemble the wording and presentation of Boost.Asio
|
||||
documentation. Credit goes to Christopher Kohloff for the wonderful
|
||||
Asio library and the ideas upon which Beast is built.
|
||||
|
||||
Beast would not be possible without the considerable time and patience
|
||||
contributed by David Schwartz, Edward Hennis, Howard Hinnant, Miguel Portilla,
|
||||
Nikolaos Bougalis, Scott Determan, Scott Schurr, and Ripple Labs for
|
||||
supporting its development.
|
||||
|
||||
[endsect]
|
@ -71,12 +71,12 @@
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.types.Body">Body</link></member>
|
||||
<member><link linkend="beast.types.Field">Field</link></member>
|
||||
<member><link linkend="beast.types.FieldSequence">FieldSequence</link></member>
|
||||
<member><link linkend="beast.types.Parser">Parser</link></member>
|
||||
<member><link linkend="beast.types.Reader">Reader</link></member>
|
||||
<member><link linkend="beast.types.Writer">Writer</link></member>
|
||||
<member><link linkend="beast.ref.Body">Body</link></member>
|
||||
<member><link linkend="beast.ref.Field">Field</link></member>
|
||||
<member><link linkend="beast.ref.FieldSequence">FieldSequence</link></member>
|
||||
<member><link linkend="beast.ref.Parser">Parser</link></member>
|
||||
<member><link linkend="beast.ref.Reader">Reader</link></member>
|
||||
<member><link linkend="beast.ref.Writer">Writer</link></member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
<entry valign="top">
|
||||
@ -181,11 +181,11 @@
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.types.streams.AsyncStream">AsyncStream</link></member>
|
||||
<member><link linkend="beast.types.BufferSequence">BufferSequence</link></member>
|
||||
<member><link linkend="beast.types.DynamicBuffer">DynamicBuffer</link></member>
|
||||
<member><link linkend="beast.types.streams.Stream">Stream</link></member>
|
||||
<member><link linkend="beast.types.streams.SyncStream">SyncStream</link></member>
|
||||
<member><link linkend="beast.ref.streams.AsyncStream">AsyncStream</link></member>
|
||||
<member><link linkend="beast.ref.BufferSequence">BufferSequence</link></member>
|
||||
<member><link linkend="beast.ref.DynamicBuffer">DynamicBuffer</link></member>
|
||||
<member><link linkend="beast.ref.streams.Stream">Stream</link></member>
|
||||
<member><link linkend="beast.ref.streams.SyncStream">SyncStream</link></member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
|
@ -31,8 +31,6 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:ref Reference]
|
||||
|
||||
</xsl:text>
|
||||
<xsl:for-each select="
|
||||
compounddef[@kind = 'class' or @kind = 'struct'] |
|
||||
@ -59,7 +57,6 @@
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:for-each>
|
||||
<xsl:text>
[endsect]</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<!--========== Utilities ==========-->
|
||||
@ -165,7 +162,7 @@
|
||||
<xsl:text>``['implementation-defined]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="$type='void_or_deduced'">
|
||||
<xsl:text>``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]``</xsl:text>
|
||||
<xsl:text>__void_or_deduced__</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$type"/>
|
||||
@ -1528,47 +1525,50 @@
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:choose>
|
||||
<xsl:when test="type = 'class AsyncStream'">
|
||||
<xsl:text>class ``[link beast.types.streams.AsyncStream [*AsyncStream]]``</xsl:text>
|
||||
<xsl:text>class ``[link beast.ref.streams.AsyncStream [*AsyncStream]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="type = 'class AsyncReadStream'">
|
||||
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]``</xsl:text>
|
||||
<xsl:text>class __AsyncReadStream__</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="type = 'class AsyncWriteStream'">
|
||||
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]``</xsl:text>
|
||||
<xsl:text>class __AsyncWriteStream__</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="type = 'class Body'">
|
||||
<xsl:text>class ``[link beast.types.Body [*Body]]``</xsl:text>
|
||||
<xsl:text>class ``[link beast.ref.Body [*Body]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="type = 'class BufferSequence'">
|
||||
<xsl:text>class ``[link beast.types.BufferSequence [*BufferSequence]]``</xsl:text>
|
||||
<xsl:text>class ``[link beast.ref.BufferSequence [*BufferSequence]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="(type = 'class' or type = 'class...') and declname = 'BufferSequence'">
|
||||
<xsl:value-of select="type"/>
|
||||
<xsl:text> ``[link beast.types.BufferSequence [*BufferSequence]]``</xsl:text>
|
||||
<xsl:text> ``[link beast.ref.BufferSequence [*BufferSequence]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'CompletionHandler' or type = 'class CompletionHandler'">
|
||||
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]``</xsl:text>
|
||||
<xsl:text>class __CompletionHandler__</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'ConstBufferSequence' or type = 'class ConstBufferSequence'">
|
||||
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]``</xsl:text>
|
||||
<xsl:text>class __ConstBufferSequence__</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'DynamicBuffer' or type = 'class DynamicBuffer'">
|
||||
<xsl:text>class ``[link beast.types.DynamicBuffer [*DynamicBuffer]]``</xsl:text>
|
||||
<xsl:text>class ``[link beast.ref.DynamicBuffer [*DynamicBuffer]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'MutableBufferSequence' or type = 'class MutableBufferSequence'">
|
||||
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]``</xsl:text>
|
||||
<xsl:text>class __MutableBufferSequence__</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Parser' or type = 'class Parser'">
|
||||
<xsl:text>class ``[link beast.ref.Parser [*Parser]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'Stream' or type = 'class Stream'">
|
||||
<xsl:text>class ``[link beast.types.streams.Stream [*Stream]]``</xsl:text>
|
||||
<xsl:text>class ``[link beast.ref.streams.Stream [*Stream]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="type = 'class SyncStream'">
|
||||
<xsl:text>class ``[link beast.types.streams.SyncStream [*SyncStream]]``</xsl:text>
|
||||
<xsl:text>class ``[link beast.ref.streams.SyncStream [*SyncStream]]``</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'SyncReadStream' or type = 'class SyncReadStream'">
|
||||
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]``</xsl:text>
|
||||
<xsl:text>class __SyncReadStream__</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="declname = 'SyncWriteStream' or type = 'class SyncWriteStream'">
|
||||
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]``</xsl:text>
|
||||
<xsl:text>class __SyncWriteStream__</xsl:text>
|
||||
</xsl:when>
|
||||
|
||||
<xsl:when test="declname = 'T'">
|
||||
|
@ -109,51 +109,6 @@ INPUT = \
|
||||
../include/beast/websocket \
|
||||
../include/beast/doc_debug.hpp \
|
||||
|
||||
../include/beast/async_completion.hpp \
|
||||
../include/beast/basic_streambuf.hpp \
|
||||
../include/beast/bind_handler.hpp \
|
||||
../include/beast/buffer_cat.hpp \
|
||||
../include/beast/buffers_adapter.hpp \
|
||||
../include/beast/consuming_buffers.hpp \
|
||||
../include/beast/handler_alloc.hpp \
|
||||
../include/beast/http.hpp \
|
||||
../include/beast/placeholders.hpp \
|
||||
../include/beast/prepare_buffers.hpp \
|
||||
../include/beast/static_streambuf.hpp \
|
||||
../include/beast/streambuf.hpp \
|
||||
../include/beast/streambuf_readstream.hpp \
|
||||
../include/beast/to_string.hpp \
|
||||
../include/beast/type_check.hpp \
|
||||
../include/beast/websocket.hpp \
|
||||
../include/beast/write_streambuf.hpp \
|
||||
../include/beast/http/basic_headers.hpp \
|
||||
../include/beast/http/basic_parser_v1.hpp \
|
||||
../include/beast/http/body_writer.hpp \
|
||||
../include/beast/http/chunk_encode.hpp \
|
||||
../include/beast/http/empty_body.hpp \
|
||||
../include/beast/http/error.hpp \
|
||||
../include/beast/http/fields.hpp \
|
||||
../include/beast/http/headers.hpp \
|
||||
../include/beast/http/message.hpp \
|
||||
../include/beast/http/message_v1.hpp \
|
||||
../include/beast/http/method.hpp \
|
||||
../include/beast/http/parse_error.hpp \
|
||||
../include/beast/http/parser.hpp \
|
||||
../include/beast/http/read.hpp \
|
||||
../include/beast/http/resume_context.hpp \
|
||||
../include/beast/http/rfc2616.hpp \
|
||||
../include/beast/http/streambuf_body.hpp \
|
||||
../include/beast/http/string_body.hpp \
|
||||
../include/beast/http/type_check.hpp \
|
||||
../include/beast/http/write.hpp \
|
||||
../include/beast/websocket/error.hpp \
|
||||
../include/beast/websocket/option.hpp \
|
||||
../include/beast/websocket/rfc6455.hpp \
|
||||
../include/beast/websocket/ssl.hpp \
|
||||
../include/beast/websocket/static_string.hpp \
|
||||
../include/beast/websocket/stream.hpp \
|
||||
../include/beast/websocket/teardown.hpp \
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS =
|
||||
RECURSIVE = NO
|
||||
|
@ -5,7 +5,11 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:Body Body]
|
||||
[section:Body Body requirements]
|
||||
|
||||
A [*Body] type is supplied as a template argument to the __message__ class. It
|
||||
controls both the type of the data member of the resulting message object, and
|
||||
the algorithms used during parsing and serialization.
|
||||
|
||||
In this table:
|
||||
|
||||
@ -22,17 +26,12 @@ In this table:
|
||||
will be not movable or not copyable.
|
||||
]
|
||||
]
|
||||
[
|
||||
[`X:value_type{}`]
|
||||
[]
|
||||
[`DefaultConstructible`]
|
||||
]
|
||||
[
|
||||
[`Body::reader`]
|
||||
[]
|
||||
[
|
||||
If present, a type meeting the requirements of
|
||||
[link beast.types.Reader [*`Reader`]].
|
||||
[link beast.ref.Reader [*`Reader`]].
|
||||
Provides an implementation to parse the body.
|
||||
]
|
||||
]
|
||||
@ -41,7 +40,7 @@ In this table:
|
||||
[]
|
||||
[
|
||||
If present, a type meeting the requirements of
|
||||
[link beast.types.Writer [*`Writer`]].
|
||||
[link beast.ref.Writer [*`Writer`]].
|
||||
Provides an implementation to serialize the body.
|
||||
]
|
||||
]
|
||||
|
@ -5,7 +5,7 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:BufferSequence BufferSequence]
|
||||
[section:BufferSequence BufferSequence requirements]
|
||||
|
||||
A `BufferSequence` is a type meeting either of the following requirements:
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:DynamicBuffer DynamicBuffer]
|
||||
[section:DynamicBuffer DynamicBuffer requirements]
|
||||
|
||||
A dynamic buffer encapsulates memory storage that may be automatically resized
|
||||
as required, where the memory is divided into an input sequence followed by an
|
||||
@ -27,7 +27,7 @@ implementation strategies:
|
||||
|
||||
* A sequence of one or more octet arrays of varying sizes. Additional octet
|
||||
array objects are appended to the sequence to accommodate changes in the
|
||||
size of the character sequence. This is the implementation approached
|
||||
size of the character sequence. This is the implementation approach
|
||||
currently offered by [link beast.ref.basic_streambuf `basic_streambuf`].
|
||||
|
||||
In the table below:
|
||||
@ -88,7 +88,7 @@ In the table below:
|
||||
]
|
||||
[
|
||||
[`a.prepare(n)`]
|
||||
[`X:mutable_buffers_type`]
|
||||
[`X::mutable_buffers_type`]
|
||||
[
|
||||
Returns a mutable buffer sequence u representing the output sequence,
|
||||
and where `buffer_size(u) == n`. The dynamic buffer reallocates memory
|
||||
|
@ -5,7 +5,7 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:Field Field]
|
||||
[section:Field Field requirements]
|
||||
|
||||
A [*`Field`] represents a single HTTP header field/value pair.
|
||||
|
||||
|
@ -5,10 +5,11 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:FieldSequence FieldSequence]
|
||||
[section:FieldSequence FieldSequence requirements]
|
||||
|
||||
A [*`FieldSequence`] is an iterable container whose value type meets
|
||||
the requirements of [link beast.types.Field [*`Field`]].
|
||||
the requirements of [link beast.ref.Field [*`Field`]]. Objects meeting
|
||||
these requirements are serializable.
|
||||
|
||||
In this table:
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:Parser Parser]
|
||||
[section:Parser Parser requirements]
|
||||
|
||||
A [*`Parser`] is used to deserialize HTTP/1 messages from [link beast.types.streams streams].
|
||||
A [*`Parser`] is used to deserialize HTTP/1 messages from [link beast.ref.streams streams].
|
||||
Objects of this type are used with [link beast.ref.http__parse http::parse] and
|
||||
[link beast.ref.http__async_parse http::async_parse].
|
||||
|
||||
@ -17,7 +17,7 @@ In this table:
|
||||
|
||||
* `a` denotes a value of type `X`.
|
||||
|
||||
* `b` is a value meeting the requirements of [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConvertibleToConstBuffer.html [*`ConvertibleToConstBuffer`]].
|
||||
* `b` is a value meeting the requirements of [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*`ConstBufferSequence`]].
|
||||
|
||||
* `ec` is a value of type [link beast.ref.error_code `error_code&`].
|
||||
|
||||
@ -34,11 +34,11 @@ In this table:
|
||||
[`a.write(b, ec)`]
|
||||
[`std::size_t`]
|
||||
[
|
||||
Parses the octets in the specified input buffer sequentially until
|
||||
an error occurs, the end of the buffer is reached, or a complete
|
||||
HTTP/1 message has been parsed. If an error occurs, `ec` is set
|
||||
to the error code and parsing stops. This function returns the
|
||||
number of bytes consumed from the input buffer.
|
||||
Sequentially parses the octets in the specified input buffer or input
|
||||
buffer sequence until an error occurs, the end of the buffer is reached,
|
||||
or a complete HTTP/1 message has been parsed. If an error occurs, `ec`
|
||||
is set to the error code and parsing stops. Upon success, this function
|
||||
returns the number of bytes used from the input.
|
||||
]
|
||||
]
|
||||
[
|
||||
|
@ -5,7 +5,7 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:Reader Reader]
|
||||
[section:Reader Reader requirements]
|
||||
|
||||
Parser implementations will construct the corresponding `reader` object
|
||||
during the parse. This customization point allows the Body to determine
|
||||
|
@ -5,7 +5,7 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:streams Streams]
|
||||
[section:streams Streams requirements]
|
||||
|
||||
Stream types represent objects capable of performing synchronous or
|
||||
asynchronous I/O. They are based on concepts from `boost::asio`.
|
||||
|
@ -5,7 +5,7 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:Writer Writer]
|
||||
[section:Writer Writer requirements]
|
||||
|
||||
A `Writer` serializes the message body. The implementation creates an instance
|
||||
of this type when serializing a message, and calls into it zero or more times
|
||||
|
@ -7,6 +7,22 @@
|
||||
|
||||
[section:websocket WebSocket]
|
||||
|
||||
[block '''
|
||||
<informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist>
|
||||
<member><link linkend="beast.websocket.creation">Creation</link></member>
|
||||
<member><link linkend="beast.websocket.connections">Making connections</link></member>
|
||||
<member><link linkend="beast.websocket.handshaking">Handshaking</link></member>
|
||||
<member><link linkend="beast.websocket.messages">Messages</link></member>
|
||||
<member><link linkend="beast.websocket.frames">Frames</link></member>
|
||||
<member><link linkend="beast.websocket.controlframes">Control frames</link></member>
|
||||
<member><link linkend="beast.websocket.pongs">Pong messages</link></member>
|
||||
<member><link linkend="beast.websocket.buffers">Buffers</link></member>
|
||||
<member><link linkend="beast.websocket.async">Asynchronous interface</link></member>
|
||||
<member><link linkend="beast.websocket.io_service">The io_service</link></member>
|
||||
<member><link linkend="beast.websocket.threads">Thread Safety</link></member>
|
||||
</simplelist></entry></row></tbody></tgroup></informaltable>
|
||||
''']
|
||||
|
||||
The WebSocket Protocol enables two-way communication between a client
|
||||
running untrusted code in a controlled environment to a remote host that has
|
||||
opted-in to communications from that code. The protocol consists of an opening
|
||||
@ -22,48 +38,12 @@ C++ approach.
|
||||
The WebSocket protocol is described fully in
|
||||
[@https://tools.ietf.org/html/rfc6455 rfc6455]
|
||||
|
||||
[note
|
||||
The following documentation assumes familiarity with both
|
||||
Boost.Asio and the WebSocket protocol specification described in __rfc6455__.
|
||||
]
|
||||
|
||||
|
||||
[section:motivation Motivation]
|
||||
|
||||
Today's web applications increasingly rely on alternatives to standard HTTP
|
||||
to achieve performance and/or responsiveness. While WebSocket implementations
|
||||
are widely available in common web development languages such as Javascript,
|
||||
good implementations in C++ are scarce. A survey of existing C++ WebSocket
|
||||
solutions reveals interfaces which lack symmetry, impose performance penalties,
|
||||
and needlessly restrict implementation strategies.
|
||||
|
||||
Beast.WebSocket is built on Boost.Asio, a robust cross platform networking
|
||||
framework that is part of Boost and also offered as a standalone library.
|
||||
A proposal to add networking functionality to the C++ standard library,
|
||||
based on Boost.Asio, is under consideration by the standards committee.
|
||||
Since the final approved networking interface for the C++ standard library
|
||||
will likely closely resemble the current interface of Boost.Asio, it is
|
||||
logical for Beast.WebSocket to use Boost.Asio as its network transport.
|
||||
|
||||
Beast.WebSocket takes advantage of Boost.Asio's extensible asynchronous
|
||||
model, handler allocation, and handler invocation hooks. Calls to
|
||||
Beast.WebSocket asynchronous initiation functions allow callers the choice
|
||||
of using a completion handler, stackful or stackless coroutines, futures,
|
||||
or user defined customizations (for example, Boost.Fiber). The
|
||||
implementation uses handler invocation hooks
|
||||
([@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]),
|
||||
providing execution guarantees on composed operations in a manner
|
||||
identical to Boost.Asio. The implementation also uses handler allocation hooks
|
||||
([@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`])
|
||||
when allocating memory internally for composed operations.
|
||||
|
||||
There is no need for inheritance or virtual members in a
|
||||
[link beast.ref.websocket__stream `beast::websocket::stream`].
|
||||
All operations are templated and transparent to the compiler, allowing for
|
||||
maximum inlining and optimization.
|
||||
|
||||
[note The documentation which follows assumes familiarity with
|
||||
both Boost.Asio and the WebSocket protocol specification described in
|
||||
[@https://tools.ietf.org/html/rfc6455 rfc6455] ]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:creation Creation]
|
||||
@ -71,15 +51,15 @@ both Boost.Asio and the WebSocket protocol specification described in
|
||||
The interface to Beast's WebSocket implementation is a single template
|
||||
class [link beast.ref.websocket__stream `beast::websocket::stream`] which
|
||||
wraps a "next layer" object. The next layer object must meet the requirements
|
||||
of [link beast.types.streams.SyncStream [*`SyncReadStream`]] if synchronous
|
||||
of [link beast.ref.streams.SyncStream [*`SyncReadStream`]] if synchronous
|
||||
operations are performed, or
|
||||
[link beast.types.streams.AsyncStream [*`AsyncStream`]] if asynchronous
|
||||
[link beast.ref.streams.AsyncStream [*`AsyncStream`]] if asynchronous
|
||||
operations are performed, or both. Arguments supplied during construction are
|
||||
passed to next layer's constructor. Here we declare a websocket stream over
|
||||
a TCP/IP socket with ownership of the socket:
|
||||
```
|
||||
boost::asio::io_service ios;
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(ios);
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
|
||||
```
|
||||
|
||||
[heading Using SSL]
|
||||
@ -92,8 +72,8 @@ argument when constructing the stream.
|
||||
#include <boost/asio/ssl.hpp>
|
||||
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
|
||||
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ws(ios, ctx);
|
||||
boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23};
|
||||
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ws{ios, ctx};
|
||||
```
|
||||
|
||||
[note
|
||||
@ -108,7 +88,7 @@ to wrap an object that already exists. This socket can be moved in:
|
||||
```
|
||||
boost::asio::ip::tcp::socket&& sock;
|
||||
...
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(std::move(sock));
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{std::move(sock)};
|
||||
```
|
||||
|
||||
Or, the wrapper can be constructed with a non-owning reference. In
|
||||
@ -117,35 +97,37 @@ underlying socket being wrapped:
|
||||
```
|
||||
boost::asio::ip::tcp::socket sock;
|
||||
...
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
|
||||
```
|
||||
|
||||
The layer being wrapped can be accessed through the websocket's "next layer",
|
||||
permitting callers to interact directly with its interface.
|
||||
```
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
|
||||
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ws(ios, ctx);
|
||||
boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23};
|
||||
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ws{ios, ctx};
|
||||
...
|
||||
ws.next_layer().shutdown(); // ssl::stream shutdown
|
||||
```
|
||||
|
||||
[important Initiating read and write operations on the next layer while
|
||||
websocket operations are being performed can break invariants, and
|
||||
result in undefined behavior. ]
|
||||
[warning
|
||||
Initiating read and write operations on the next layer while
|
||||
stream operations are being performed can break invariants, and
|
||||
result in undefined behavior.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:connecting Making connections]
|
||||
[section:connections Making connections]
|
||||
|
||||
Connections are established by using the interfaces which already exist
|
||||
for the next layer. For example, making an outgoing connection:
|
||||
```
|
||||
std::string const host = "mywebapp.com";
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::resolver r(ios);
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(ios);
|
||||
boost::asio::ip::tcp::resolver r{ios};
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
|
||||
boost::asio::connect(ws.next_layer(),
|
||||
r.resolve(boost::asio::ip::tcp::resolver::query{host, "ws"}));
|
||||
```
|
||||
@ -154,12 +136,14 @@ Accepting an incoming connection:
|
||||
```
|
||||
void do_accept(boost::asio::ip::tcp::acceptor& acceptor)
|
||||
{
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(acceptor.get_io_service());
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{acceptor.get_io_service()};
|
||||
acceptor.accept(ws.next_layer());
|
||||
}
|
||||
```
|
||||
|
||||
[note Examples use synchronous interfaces for clarity of exposition. ]
|
||||
[note
|
||||
Examples use synchronous interfaces for clarity of exposition.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
@ -171,16 +155,17 @@ A WebSocket session begins when one side sends the HTTP Upgrade request
|
||||
for websocket, and the other side sends an appropriate HTTP response
|
||||
indicating that the request was accepted and that the connection has
|
||||
been upgraded. The HTTP Upgrade request must include the Host HTTP field,
|
||||
and the URI of the resource to request. `handshake` is used to send the
|
||||
and the URI of the resource to request.
|
||||
[link beast.ref.websocket__stream.handshake `handshake`] is used to send the
|
||||
request with the required host and resource strings.
|
||||
```
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(ios);
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
|
||||
...
|
||||
ws.set_option(beast::websocket::keep_alive(true));
|
||||
ws.handshake("ws.example.com:80", "/cgi-bin/bitcoin-prices");
|
||||
```
|
||||
|
||||
The [link beast.ref.websocket__stream `beast::websocket::stream`] automatically
|
||||
The [link beast.ref.websocket__stream `stream`] automatically
|
||||
handles receiving and processing the HTTP response to the handshake request.
|
||||
The call to handshake is successful if a HTTP response is received with the
|
||||
101 "Switching Protocols" status code. On failure, an error is returned or an
|
||||
@ -190,7 +175,7 @@ open for a subsequent handshake attempt
|
||||
Performing a handshake for an incoming websocket upgrade request operates
|
||||
similarly. If the handshake fails, an error is returned or exception thrown:
|
||||
```
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(ios);
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
|
||||
...
|
||||
ws.accept();
|
||||
```
|
||||
@ -205,7 +190,7 @@ void do_accept(boost::asio::ip::tcp::socket& sock)
|
||||
boost::asio::streambuf sb;
|
||||
boost::asio::read_until(sock, sb, "\r\n\r\n");
|
||||
...
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
|
||||
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
|
||||
ws.accept(sb.data());
|
||||
...
|
||||
}
|
||||
@ -218,10 +203,10 @@ void do_accept(boost::asio::ip::tcp::socket& sock)
|
||||
{
|
||||
boost::asio::streambuf sb;
|
||||
beast::http::request<http::empty_body> request;
|
||||
beast::http::read(sock, request);
|
||||
beast::http::read(sock, sb, request);
|
||||
if(beast::http::is_upgrade(request))
|
||||
{
|
||||
websocket::stream<ip::tcp::socket&> ws(sock);
|
||||
websocket::stream<ip::tcp::socket&> ws{sock};
|
||||
ws.accept(request);
|
||||
...
|
||||
}
|
||||
@ -244,15 +229,17 @@ void echo(beast::websocket::stream<boost::asio::ip::tcp::socket>& ws)
|
||||
beast::websocket::opcode::value op;
|
||||
ws.read(sb);
|
||||
|
||||
ws.set_option(beast::websocket::message_type(op));
|
||||
ws.set_option(beast::websocket::message_type{op});
|
||||
ws.write(sb.data());
|
||||
sb.consume(sb.size());
|
||||
}
|
||||
```
|
||||
|
||||
[important Calls to [link beast.ref.websocket__stream.set_option `set_option`]
|
||||
must be made from the same implicit or explicit strand as that used to perform
|
||||
other operations. ]
|
||||
[important
|
||||
Calls to [link beast.ref.websocket__stream.set_option `set_option`]
|
||||
must be made from the same implicit or explicit strand as that used
|
||||
to perform other operations.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
@ -280,9 +267,9 @@ void echo(beast::websocket::stream<boost::asio::ip::tcp::socket>& ws)
|
||||
if(fi.fin)
|
||||
break;
|
||||
}
|
||||
ws.set_option(beast::websocket::message_type(fi.op));
|
||||
ws.set_option(beast::websocket::message_type{fi.op});
|
||||
beast::consuming_buffers<
|
||||
beast::streambuf::const_buffers_type> cb(sb.data());
|
||||
beast::streambuf::const_buffers_type> cb{sb.data()};
|
||||
for(;;)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
@ -321,7 +308,7 @@ of the frames making up the message. The automatic fragment size option
|
||||
gives callers control over the size of these frames:
|
||||
```
|
||||
...
|
||||
ws.set_option(beast::websocket::auto_fragment_size(8192));
|
||||
ws.set_option(beast::websocket::auto_fragment_size{8192});
|
||||
```
|
||||
|
||||
The WebSocket protocol defines a procedure and control message for initiating
|
||||
@ -342,9 +329,8 @@ error, a read operation is required. ]
|
||||
[section:pongs Pong messages]
|
||||
|
||||
To receive pong control frames, callers may register a "pong callback" using
|
||||
[link beast.ref.websocket__stream.set_option `set_option`]:
|
||||
|
||||
the following signature:
|
||||
[link beast.ref.websocket__stream.set_option `set_option`]. The object provided
|
||||
with this option should be callable with the following signature:
|
||||
```
|
||||
void on_pong(ping_data const& payload);
|
||||
...
|
||||
@ -373,7 +359,7 @@ handler of the corresponding read function.]
|
||||
|
||||
Because calls to read data may return a variable amount of bytes, the
|
||||
interface to calls that read data require an object that meets the requirements
|
||||
of [link beast.types.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on
|
||||
of [link beast.ref.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on
|
||||
[@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`].
|
||||
|
||||
The implementation does not perform queueing or buffering of messages. If
|
||||
@ -429,7 +415,7 @@ use or require threads.
|
||||
|
||||
|
||||
|
||||
[section:safety Thread Safety]
|
||||
[section:threads Thread Safety]
|
||||
|
||||
Like a regular asio socket, a [link beast.ref.websocket__stream `stream`] is
|
||||
not thread safe. Callers are responsible for synchronizing operations on the
|
||||
|
@ -71,9 +71,7 @@ template<class T>
|
||||
struct is_Body
|
||||
{
|
||||
using type = std::integral_constant<bool,
|
||||
has_value_type<T>::value &&
|
||||
std::is_default_constructible<
|
||||
typename extract_value_type<T>::type>::value
|
||||
has_value_type<T>::value
|
||||
>;
|
||||
};
|
||||
|
||||
@ -92,7 +90,7 @@ class is_Parser
|
||||
template<class U, class R =
|
||||
std::is_convertible<decltype(
|
||||
std::declval<U>().write(
|
||||
std::declval<boost::asio::const_buffer const&>(),
|
||||
std::declval<boost::asio::const_buffers_1 const&>(),
|
||||
std::declval<error_code&>())),
|
||||
std::size_t>>
|
||||
static R check2(int);
|
||||
|
@ -72,8 +72,8 @@ struct frame_info
|
||||
For asynchronous operations, the type must support the
|
||||
@b `AsyncStream` concept.
|
||||
|
||||
@note A stream object must not be destroyed while there are
|
||||
pending asynchronous operations associated with it.
|
||||
@note A stream object must not be moved or destroyed while there
|
||||
are pending asynchronous operations associated with it.
|
||||
|
||||
@par Concepts
|
||||
@b `AsyncStream`,
|
||||
@ -1018,7 +1018,8 @@ public:
|
||||
hold all the message payload bytes (which may be zero in length).
|
||||
|
||||
Control frames encountered while reading frame or message data
|
||||
are handled automatically. Pings are replied to, pongs are noted,
|
||||
are handled automatically. Pings are replied to automatically,
|
||||
pongs are routed to the pong callback if the option is set,
|
||||
and close frames initiate the WebSocket close procedure. When a
|
||||
close frame is received, this call will eventually return
|
||||
@ref error::closed. Because of the need to handle control frames,
|
||||
@ -1053,7 +1054,8 @@ public:
|
||||
hold all the message payload bytes (which may be zero in length).
|
||||
|
||||
Control frames encountered while reading frame or message data
|
||||
are handled automatically. Pings are replied to, pongs are noted,
|
||||
are handled automatically. Pings are replied to automatically,
|
||||
pongs are routed to the pong callback if the option is set,
|
||||
and close frames initiate the WebSocket close procedure. When a
|
||||
close frame is received, this call will eventually return
|
||||
@ref error::closed. Because of the need to handle control frames,
|
||||
@ -1152,7 +1154,8 @@ public:
|
||||
fi.fin == true, and zero bytes placed into the stream buffer.
|
||||
|
||||
Control frames encountered while reading frame or message data
|
||||
are handled automatically. Pings are replied to, pongs are noted,
|
||||
are handled automatically. Pings are replied to automatically,
|
||||
pongs are routed to the pong callback if the option is set,
|
||||
and close frames initiate the WebSocket close procedure. When a
|
||||
close frame is received, this call will eventually return
|
||||
@ref error::closed. Because of the need to handle control frames,
|
||||
@ -1190,7 +1193,8 @@ public:
|
||||
fi.fin == true, and zero bytes placed into the stream buffer.
|
||||
|
||||
Control frames encountered while reading frame or message data
|
||||
are handled automatically. Pings are replied to, pongs are noted,
|
||||
are handled automatically. Pings are replied to automatically,
|
||||
pongs are routed to the pong callback if the option is set,
|
||||
and close frames initiate the WebSocket close procedure. When a
|
||||
close frame is received, this call will eventually return
|
||||
@ref error::closed. Because of the need to handle control frames,
|
||||
@ -1233,7 +1237,8 @@ public:
|
||||
the stream buffer.
|
||||
|
||||
Control frames encountered while reading frame or message data
|
||||
are handled automatically. Pings are replied to, pongs are noted,
|
||||
are handled automatically. Pings are replied to automatically,
|
||||
pongs are routed to the pong callback if the option is set,
|
||||
and close frames initiate the WebSocket close procedure. When a
|
||||
close frame is received, this call will eventually return
|
||||
@ref error::closed. Because of the need to handle control frames,
|
||||
|
20
index.html
Normal file
20
index.html
Normal file
@ -0,0 +1,20 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="doc/html/index.html">doc/html/index.html</a>
|
||||
<hr>
|
||||
<tt>
|
||||
Boost.Beast<br>
|
||||
<br>
|
||||
Copyright (C) 2013-2016 Vinnie Falco<br>
|
||||
<br>
|
||||
Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file LICENSE_1_0.txt or copy at
|
||||
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||
<br>
|
||||
</tt>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user