mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
WebSocket Decorator is a socket option (API Change):
This changes the interface used to apply a decorator to the HTTP request or response messages used to perform the WebSocket handshake as follows: * Add the `stream_base::decorator` option object * Add `stream::set_option` overload to set the decorator from the option * The decorator applies to all client and server handshakes performed on the stream after the option is set. * Overloads of the following functions which accept a Decorator are deprecated: - accept, accept_ex - handshake, handshake_ex - async_accept, async_accept_ex - async_handshake, async_handshake_ex Actions Required: * Code which passes decorator to any `websocket::stream` member function should call `stream::set_option` instead with a newly constructed `stream_base::decorator` object containing the decorator. Alternatively, the macro `BOOST_BEAST_ALLOW_DEPRECATED` may be defined to 1.
This commit is contained in:
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
[section Handshaking (Clients)]
|
[section Handshaking (Clients)]
|
||||||
|
|
||||||
A WebSocket session begins when a client sends the HTTP/1
|
A WebSocket session begins when a client sends the HTTP/1.1
|
||||||
[@https://tools.ietf.org/html/rfc7230#section-6.7 Upgrade]
|
[@https://tools.ietf.org/html/rfc7230#section-6.7 Upgrade]
|
||||||
request for
|
request for
|
||||||
[@https://tools.ietf.org/html/rfc6455#section-1.3 websocket],
|
[@https://tools.ietf.org/html/rfc6455#section-1.3 websocket],
|
||||||
@ -19,69 +19,39 @@ The Upgrade request must include the
|
|||||||
[@https://tools.ietf.org/html/rfc7230#section-5.4 Host]
|
[@https://tools.ietf.org/html/rfc7230#section-5.4 Host]
|
||||||
field, and the
|
field, and the
|
||||||
[@https://tools.ietf.org/html/rfc7230#section-5.3 target]
|
[@https://tools.ietf.org/html/rfc7230#section-5.3 target]
|
||||||
of the resource to request. The stream member functions
|
of the resource to request.
|
||||||
[link beast.ref.boost__beast__websocket__stream.handshake.overload1 `handshake`] and
|
A typical HTTP Upgrade request created and sent by the implementation
|
||||||
[link beast.ref.boost__beast__websocket__stream.async_handshake.overload1 `async_handshake`]
|
will look like this:
|
||||||
are used to send the request with the required host and target strings.
|
|
||||||
|
|
||||||
[ws_snippet_8]
|
[table WebSocket HTTP Upgrade Request
|
||||||
|
|
||||||
The implementation will create and send a request that typically
|
|
||||||
looks like this:
|
|
||||||
|
|
||||||
[table WebSocket Upgrade HTTP Request
|
|
||||||
[[Serialized Octets][Description]]
|
[[Serialized Octets][Description]]
|
||||||
[[
|
[[
|
||||||
```
|
```
|
||||||
GET / HTTP/1.1
|
GET / HTTP/1.1
|
||||||
Host: localhost
|
Host: www.example.com
|
||||||
Upgrade: websocket
|
Upgrade: websocket
|
||||||
Connection: upgrade
|
Connection: upgrade
|
||||||
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
|
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
|
||||||
Sec-WebSocket-Version: 13
|
Sec-WebSocket-Version: 13
|
||||||
User-Agent: Beast
|
User-Agent: Boost.Beast/216
|
||||||
```
|
```
|
||||||
][
|
][
|
||||||
The host and target parameters become part of the Host field
|
The host and target parameters become part of the Host field
|
||||||
and request-target in the resulting HTTP request. The key is
|
and request-target in the resulting HTTP request. The key is
|
||||||
generated by the implementation. Callers may add fields or
|
generated by the implementation. Callers may add fields or
|
||||||
modify fields by providing a ['decorator], described below.
|
modify fields by providing a ['decorator], described later.
|
||||||
]]]
|
]]]
|
||||||
|
|
||||||
[heading Decorators]
|
The
|
||||||
|
[link beast.ref.boost__beast__websocket__stream `stream`]
|
||||||
|
member functions
|
||||||
|
[link beast.ref.boost__beast__websocket__stream.handshake `handshake`] and
|
||||||
|
[link beast.ref.boost__beast__websocket__stream.async_handshake `async_handshake`]
|
||||||
|
are used to send the request with the required host and target strings. The
|
||||||
|
code below sends the WebSocket HTTP Upgrade request, then reads and processes
|
||||||
|
the response:
|
||||||
|
|
||||||
If the caller wishes to add or modify fields, the member functions
|
[code_websocket_3_client_1]
|
||||||
[link beast.ref.boost__beast__websocket__stream.handshake_ex `handshake_ex`] and
|
|
||||||
[link beast.ref.boost__beast__websocket__stream.async_handshake_ex `async_handshake_ex`]
|
|
||||||
are provided which allow an additional function object, called a
|
|
||||||
['decorator], to be passed. The decorator is invoked to modify
|
|
||||||
the HTTP Upgrade request as needed. This example sets a subprotocol
|
|
||||||
on the request:
|
|
||||||
|
|
||||||
[ws_snippet_9]
|
|
||||||
|
|
||||||
The HTTP Upgrade request produced by the previous call will look thusly:
|
|
||||||
|
|
||||||
[table Decorated WebSocket Upgrade HTTP Request
|
|
||||||
[[Serialized Octets][Description]]
|
|
||||||
[[
|
|
||||||
```
|
|
||||||
GET / HTTP/1.1
|
|
||||||
Host: localhost
|
|
||||||
Upgrade: websocket
|
|
||||||
Connection: upgrade
|
|
||||||
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
|
|
||||||
Sec-WebSocket-Version: 13
|
|
||||||
Sec-WebSocket-Protocol: xmpp;ws-chat
|
|
||||||
User-Agent: Beast
|
|
||||||
```
|
|
||||||
][
|
|
||||||
Undefined behavior results if the decorator modifies the fields
|
|
||||||
specific to perform the WebSocket Upgrade , such as the Upgrade
|
|
||||||
and Connection fields.
|
|
||||||
]]]
|
|
||||||
|
|
||||||
[heading Filtering]
|
|
||||||
|
|
||||||
When a client receives an HTTP Upgrade response from the server indicating
|
When a client receives an HTTP Upgrade response from the server indicating
|
||||||
a successful upgrade, the caller may wish to perform additional validation
|
a successful upgrade, the caller may wish to perform additional validation
|
||||||
@ -92,6 +62,6 @@ received HTTP message in an output reference argument of type
|
|||||||
[link beast.ref.boost__beast__websocket__response_type `response_type`]
|
[link beast.ref.boost__beast__websocket__response_type `response_type`]
|
||||||
as follows:
|
as follows:
|
||||||
|
|
||||||
[ws_snippet_10]
|
[code_websocket_3_client_2]
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
@ -18,16 +18,10 @@ is received with the
|
|||||||
status code. On failure, an error is returned or an exception is thrown.
|
status code. On failure, an error is returned or an exception is thrown.
|
||||||
Depending on the keep alive setting, the connection may remain open for
|
Depending on the keep alive setting, the connection may remain open for
|
||||||
a subsequent handshake attempt.
|
a subsequent handshake attempt.
|
||||||
|
A typical HTTP Upgrade response created and sent by the implementation
|
||||||
|
upon receiving an upgrade request handshake will look like this:
|
||||||
|
|
||||||
Performing a handshake for an incoming websocket upgrade request operates
|
[table WebSocket Upgrade HTTP Response
|
||||||
similarly. If the handshake fails, an error is returned or exception thrown:
|
|
||||||
|
|
||||||
[ws_snippet_11]
|
|
||||||
|
|
||||||
Successful WebSocket Upgrade responses generated by the implementation will
|
|
||||||
typically look like this:
|
|
||||||
|
|
||||||
[table Decorated WebSocket Upgrade HTTP Request
|
|
||||||
[[Serialized Octets][Description]]
|
[[Serialized Octets][Description]]
|
||||||
[[
|
[[
|
||||||
```
|
```
|
||||||
@ -35,7 +29,7 @@ typically look like this:
|
|||||||
Upgrade: websocket
|
Upgrade: websocket
|
||||||
Connection: upgrade
|
Connection: upgrade
|
||||||
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
|
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
|
||||||
Server: Beast/40
|
Server: Boost.Beast/216
|
||||||
```
|
```
|
||||||
][
|
][
|
||||||
The
|
The
|
||||||
@ -44,39 +38,18 @@ typically look like this:
|
|||||||
the WebSocket protocol.
|
the WebSocket protocol.
|
||||||
]]]
|
]]]
|
||||||
|
|
||||||
[heading Decorators]
|
The
|
||||||
|
[link beast.ref.boost__beast__websocket__stream `stream`]
|
||||||
|
member functions
|
||||||
|
[link beast.ref.boost__beast__websocket__stream.accept `accept`] and
|
||||||
|
[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`]
|
||||||
|
are used to read the WebSocket HTTP Upgrade request handshake from a stream
|
||||||
|
already connected to an incoming peer, and then send the WebSocket HTTP
|
||||||
|
Upgrade response, as shown:
|
||||||
|
|
||||||
If the caller wishes to add or modify fields, the member functions
|
[code_websocket_3_server_1]
|
||||||
[link beast.ref.boost__beast__websocket__stream.accept_ex `accept_ex`] and
|
|
||||||
[link beast.ref.boost__beast__websocket__stream.async_accept_ex `async_accept_ex`]
|
|
||||||
are provided which allow an additional function object, called a
|
|
||||||
['decorator], to be passed. The decorator is invoked to modify
|
|
||||||
the HTTP Upgrade request as needed. This example sets the Server
|
|
||||||
field on the response:
|
|
||||||
|
|
||||||
[ws_snippet_12]
|
|
||||||
|
|
||||||
The HTTP Upgrade response produced by the previous call looks like this:
|
|
||||||
|
|
||||||
[table Decorated WebSocket Upgrade HTTP Request
|
|
||||||
[[Serialized Octets][Description]]
|
|
||||||
[[
|
|
||||||
```
|
|
||||||
HTTP/1.1 101 Switching Protocols
|
|
||||||
Upgrade: websocket
|
|
||||||
Connection: upgrade
|
|
||||||
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
|
|
||||||
Server: AcmeServer
|
|
||||||
```
|
|
||||||
][
|
|
||||||
When the Upgrade request fails, the implementation will still invoke
|
|
||||||
the decorator to modify the response. In this case, the response
|
|
||||||
object will have a status code other than 101.
|
|
||||||
|
|
||||||
Undefined behavior results when the upgrade request is successful
|
|
||||||
and the decorator modifies the fields specific to perform the
|
|
||||||
WebSocket Upgrade, such as the Upgrade and Connection fields.
|
|
||||||
]]]
|
|
||||||
|
|
||||||
[heading Passing HTTP Requests]
|
[heading Passing HTTP Requests]
|
||||||
|
|
||||||
@ -87,16 +60,19 @@ the incoming HTTP request is a WebSocket Upgrade request, the function
|
|||||||
|
|
||||||
Once the caller determines that the HTTP request is a WebSocket Upgrade,
|
Once the caller determines that the HTTP request is a WebSocket Upgrade,
|
||||||
additional overloads of
|
additional overloads of
|
||||||
[link beast.ref.boost__beast__websocket__stream.accept `accept`],
|
[link beast.ref.boost__beast__websocket__stream.accept `accept`] and
|
||||||
[link beast.ref.boost__beast__websocket__stream.accept_ex `accept_ex`],
|
[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`]
|
||||||
[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`], and
|
|
||||||
[link beast.ref.boost__beast__websocket__stream.async_accept_ex `async_accept_ex`]
|
|
||||||
are provided which receive the entire HTTP request header as an object
|
are provided which receive the entire HTTP request header as an object
|
||||||
to perform the handshake. In this example, the request is first read
|
to perform the handshake. By reading the request manually, the program
|
||||||
in using the HTTP algorithms, and then passed to a newly constructed
|
can handle normal HTTP requests as well as upgrades. The program may
|
||||||
|
also enforce policies based on the HTTP fields, such as Basic
|
||||||
|
Authentication. In this example, the request is first read in
|
||||||
|
using the HTTP algorithms, and then passed to a newly constructed
|
||||||
stream:
|
stream:
|
||||||
|
|
||||||
[ws_snippet_13]
|
[code_websocket_3_server_1b]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[heading Buffered Handshakes]
|
[heading Buffered Handshakes]
|
||||||
|
|
||||||
@ -106,10 +82,8 @@ the first 6 octets after accepting an incoming connection to determine
|
|||||||
if a TLS protocol is being negotiated, and choose a suitable implementation
|
if a TLS protocol is being negotiated, and choose a suitable implementation
|
||||||
at run-time. In the case where the server wishes to accept the incoming
|
at run-time. In the case where the server wishes to accept the incoming
|
||||||
request as an HTTP WebSocket Upgrade request, additional overloads of
|
request as an HTTP WebSocket Upgrade request, additional overloads of
|
||||||
[link beast.ref.boost__beast__websocket__stream.accept `accept`],
|
[link beast.ref.boost__beast__websocket__stream.accept `accept`] and
|
||||||
[link beast.ref.boost__beast__websocket__stream.accept_ex `accept_ex`],
|
[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`]
|
||||||
[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`], and
|
|
||||||
[link beast.ref.boost__beast__websocket__stream.async_accept_ex `async_accept_ex`]
|
|
||||||
are provided which receive the additional buffered octets and consume
|
are provided which receive the additional buffered octets and consume
|
||||||
them as part of the handshake.
|
them as part of the handshake.
|
||||||
|
|
||||||
@ -117,7 +91,7 @@ In this example, the server reads the initial HTTP message into the
|
|||||||
specified dynamic buffer as an octet sequence in the buffer's output
|
specified dynamic buffer as an octet sequence in the buffer's output
|
||||||
area, and later uses those octets to attempt an HTTP WebSocket Upgrade:
|
area, and later uses those octets to attempt an HTTP WebSocket Upgrade:
|
||||||
|
|
||||||
[ws_snippet_14]
|
[code_websocket_3_server_2]
|
||||||
|
|
||||||
The implementation uses a fixed-size storage area to hold buffers passed
|
The implementation uses a fixed-size storage area to hold buffers passed
|
||||||
using these functions. If an application is reaching the limit of the
|
using these functions. If an application is reaching the limit of the
|
||||||
@ -128,4 +102,6 @@ to wrap the underlying stream. The buffered handshake data may be first
|
|||||||
placed into the buffered read stream, which uses a dynamically sized
|
placed into the buffered read stream, which uses a dynamically sized
|
||||||
buffer.
|
buffer.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
79
doc/qbk/06_websocket/05_decorator.qbk
Normal file
79
doc/qbk/06_websocket/05_decorator.qbk
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
[/
|
||||||
|
Copyright (c) 2016-2017 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)
|
||||||
|
|
||||||
|
Official repository: https://github.com/boostorg/beast
|
||||||
|
]
|
||||||
|
|
||||||
|
[section:decorator Custom HTTP Fields]
|
||||||
|
|
||||||
|
For programs which need to modify either the outgoing WebSocket HTTP Upgrade
|
||||||
|
request, the outgoing WebSocket HTTP Upgrade response, or both, the stream
|
||||||
|
supports an optional property called a ['decorator]. This is a function
|
||||||
|
pointer or callable object which is invoked before the implementation
|
||||||
|
sends an HTTP message. The decorator receives a modifiable reference to
|
||||||
|
the message, allowing for modifications. The interface to this system
|
||||||
|
uses:
|
||||||
|
|
||||||
|
[table WebSocket Decorator Interface
|
||||||
|
[[Name][Description]]
|
||||||
|
[[
|
||||||
|
`request_type`
|
||||||
|
][
|
||||||
|
This is the type of the object passed to the decorator to
|
||||||
|
represent HTTP Upgrade requests.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
`response_type`
|
||||||
|
][
|
||||||
|
This is the type of the object passed to the decorator to
|
||||||
|
represent HTTP Upgrade response.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.boost__beast__websocket__stream_base__decorator `stream_base::decorator`]
|
||||||
|
][
|
||||||
|
Objects of this type are used to hold a decorator to be
|
||||||
|
set on the stream using `set_option`.
|
||||||
|
]]
|
||||||
|
[[
|
||||||
|
[link beast.ref.boost__beast__websocket__stream.set_option `stream::set_option`]
|
||||||
|
][
|
||||||
|
This function is used to set a `stream_base::decorator` on the stream.
|
||||||
|
]]
|
||||||
|
]
|
||||||
|
|
||||||
|
This declares a normal function which decorates outgoing HTTP requests:
|
||||||
|
|
||||||
|
[code_websocket_3_decorator_1b]
|
||||||
|
|
||||||
|
If a decorator is used, it must be set on the stream before any handshaking
|
||||||
|
takes place. This sets the decorator on the stream, to be used for all
|
||||||
|
subsequent calls to accept or handshake:
|
||||||
|
|
||||||
|
[code_websocket_3_decorator_1]
|
||||||
|
|
||||||
|
Alternatively, a function object may be used. Small function objects will
|
||||||
|
not incur a memory allocation. The follow code declares and sets a function
|
||||||
|
object as a decorator:
|
||||||
|
|
||||||
|
[code_websocket_3_decorator_2]
|
||||||
|
|
||||||
|
A lambda may be used in place of a named function object:
|
||||||
|
|
||||||
|
[code_websocket_3_decorator_3]
|
||||||
|
|
||||||
|
It also possible for a single decorator to handle both requests and
|
||||||
|
responses, if it is overloaded for both types either as a generic
|
||||||
|
lambda (C++14 and later) or as a class as shown here:
|
||||||
|
|
||||||
|
[code_websocket_3_decorator_4]
|
||||||
|
|
||||||
|
[important
|
||||||
|
Undefined behavior results if the decorator modifies the fields
|
||||||
|
specific to perform the WebSocket Upgrade, such as the Upgrade
|
||||||
|
or Connection fields.
|
||||||
|
]
|
||||||
|
|
||||||
|
[endsect]
|
@ -33,9 +33,10 @@ Boost.Asio with a consistent asynchronous model using a modern C++ approach.
|
|||||||
[include 02_connect.qbk]
|
[include 02_connect.qbk]
|
||||||
[include 03_client.qbk]
|
[include 03_client.qbk]
|
||||||
[include 04_server.qbk]
|
[include 04_server.qbk]
|
||||||
[include 05_messages.qbk]
|
[include 05_decorator.qbk]
|
||||||
[include 06_control.qbk]
|
[include 06_messages.qbk]
|
||||||
[include 07_teardown.qbk]
|
[include 07_control.qbk]
|
||||||
[include 08_notes.qbk]
|
[include 08_teardown.qbk]
|
||||||
|
[include 09_notes.qbk]
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
@ -132,6 +132,7 @@
|
|||||||
|
|
||||||
[import ../../test/doc/core_1_refresher.cpp]
|
[import ../../test/doc/core_1_refresher.cpp]
|
||||||
[import ../../test/doc/core_3_layers.cpp]
|
[import ../../test/doc/core_3_layers.cpp]
|
||||||
|
[import ../../test/doc/websocket_3_handshake.cpp]
|
||||||
|
|
||||||
[section:quickref Reference]
|
[section:quickref Reference]
|
||||||
'''
|
'''
|
||||||
|
@ -251,6 +251,16 @@ public:
|
|||||||
websocket::stream_base::suggested_settings(
|
websocket::stream_base::suggested_settings(
|
||||||
websocket::role_type::server));
|
websocket::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
derived().ws().set_option(
|
||||||
|
websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" advanced-server-flex");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
derived().ws().async_accept(
|
derived().ws().async_accept(
|
||||||
req,
|
req,
|
||||||
|
@ -229,10 +229,6 @@ public:
|
|||||||
websocket_session(tcp::socket socket)
|
websocket_session(tcp::socket socket)
|
||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
{
|
{
|
||||||
// Set suggested timeout settings for the websocket
|
|
||||||
ws_.set_option(
|
|
||||||
websocket::stream_base::suggested_settings(
|
|
||||||
websocket::role_type::server));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the asynchronous accept operation
|
// Start the asynchronous accept operation
|
||||||
@ -240,6 +236,20 @@ public:
|
|||||||
void
|
void
|
||||||
do_accept(http::request<Body, http::basic_fields<Allocator>> req)
|
do_accept(http::request<Body, http::basic_fields<Allocator>> req)
|
||||||
{
|
{
|
||||||
|
// Set suggested timeout settings for the websocket
|
||||||
|
ws_.set_option(
|
||||||
|
websocket::stream_base::suggested_settings(
|
||||||
|
websocket::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" advanced-server");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws_.async_accept(
|
ws_.async_accept(
|
||||||
req,
|
req,
|
||||||
|
@ -132,6 +132,15 @@ public:
|
|||||||
websocket::stream_base::suggested_settings(
|
websocket::stream_base::suggested_settings(
|
||||||
websocket::role_type::client));
|
websocket::role_type::client));
|
||||||
|
|
||||||
|
// Set a decorator to change the User-Agent of the handshake
|
||||||
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::request_type& req)
|
||||||
|
{
|
||||||
|
req.set(http::field::user_agent,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-client-async-ssl");
|
||||||
|
}));
|
||||||
|
|
||||||
// Perform the websocket handshake
|
// Perform the websocket handshake
|
||||||
ws_.async_handshake(host_, "/",
|
ws_.async_handshake(host_, "/",
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
|
@ -110,6 +110,15 @@ public:
|
|||||||
websocket::stream_base::suggested_settings(
|
websocket::stream_base::suggested_settings(
|
||||||
websocket::role_type::client));
|
websocket::role_type::client));
|
||||||
|
|
||||||
|
// Set a decorator to change the User-Agent of the handshake
|
||||||
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::request_type& req)
|
||||||
|
{
|
||||||
|
req.set(http::field::user_agent,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-client-async");
|
||||||
|
}));
|
||||||
|
|
||||||
// Perform the websocket handshake
|
// Perform the websocket handshake
|
||||||
ws_.async_handshake(host_, "/",
|
ws_.async_handshake(host_, "/",
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
|
@ -74,6 +74,15 @@ do_session(
|
|||||||
// Set a timeout on the operation
|
// Set a timeout on the operation
|
||||||
beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30));
|
beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30));
|
||||||
|
|
||||||
|
// Set a decorator to change the User-Agent of the handshake
|
||||||
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::request_type& req)
|
||||||
|
{
|
||||||
|
req.set(http::field::user_agent,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-client-coro");
|
||||||
|
}));
|
||||||
|
|
||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
ws.next_layer().async_handshake(ssl::stream_base::client, yield[ec]);
|
ws.next_layer().async_handshake(ssl::stream_base::client, yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
|
@ -74,6 +74,15 @@ do_session(
|
|||||||
websocket::stream_base::suggested_settings(
|
websocket::stream_base::suggested_settings(
|
||||||
websocket::role_type::client));
|
websocket::role_type::client));
|
||||||
|
|
||||||
|
// Set a decorator to change the User-Agent of the handshake
|
||||||
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::request_type& req)
|
||||||
|
{
|
||||||
|
req.set(http::field::user_agent,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-client-coro");
|
||||||
|
}));
|
||||||
|
|
||||||
// Perform the websocket handshake
|
// Perform the websocket handshake
|
||||||
ws.async_handshake(host, "/", yield[ec]);
|
ws.async_handshake(host, "/", yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
|
@ -73,6 +73,15 @@ int main(int argc, char** argv)
|
|||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
ws.next_layer().handshake(ssl::stream_base::client);
|
ws.next_layer().handshake(ssl::stream_base::client);
|
||||||
|
|
||||||
|
// Set a decorator to change the User-Agent of the handshake
|
||||||
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::request_type& req)
|
||||||
|
{
|
||||||
|
req.set(http::field::user_agent,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-client-coro");
|
||||||
|
}));
|
||||||
|
|
||||||
// Perform the websocket handshake
|
// Perform the websocket handshake
|
||||||
ws.handshake(host, "/");
|
ws.handshake(host, "/");
|
||||||
|
|
||||||
|
@ -60,6 +60,15 @@ int main(int argc, char** argv)
|
|||||||
// Make the connection on the IP address we get from a lookup
|
// Make the connection on the IP address we get from a lookup
|
||||||
net::connect(ws.next_layer(), results.begin(), results.end());
|
net::connect(ws.next_layer(), results.begin(), results.end());
|
||||||
|
|
||||||
|
// Set a decorator to change the User-Agent of the handshake
|
||||||
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::request_type& req)
|
||||||
|
{
|
||||||
|
req.set(http::field::user_agent,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-client-coro");
|
||||||
|
}));
|
||||||
|
|
||||||
// Perform the websocket handshake
|
// Perform the websocket handshake
|
||||||
ws.handshake(host, "/");
|
ws.handshake(host, "/");
|
||||||
|
|
||||||
|
@ -89,6 +89,15 @@ public:
|
|||||||
websocket::stream_base::suggested_settings(
|
websocket::stream_base::suggested_settings(
|
||||||
websocket::role_type::server));
|
websocket::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-server-async-ssl");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws_.async_accept(
|
ws_.async_accept(
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
|
@ -52,16 +52,26 @@ public:
|
|||||||
session(tcp::socket socket)
|
session(tcp::socket socket)
|
||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
{
|
{
|
||||||
// Set suggested timeout settings for the websocket
|
|
||||||
ws_.set_option(
|
|
||||||
websocket::stream_base::suggested_settings(
|
|
||||||
websocket::role_type::server));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the asynchronous operation
|
// Start the asynchronous operation
|
||||||
void
|
void
|
||||||
run()
|
run()
|
||||||
{
|
{
|
||||||
|
// Set suggested timeout settings for the websocket
|
||||||
|
ws_.set_option(
|
||||||
|
websocket::stream_base::suggested_settings(
|
||||||
|
websocket::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-server-async");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws_.async_accept(
|
ws_.async_accept(
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
|
@ -17,10 +17,6 @@ websocket_session(
|
|||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
, state_(state)
|
, state_(state)
|
||||||
{
|
{
|
||||||
// Set suggested timeout settings for the websocket
|
|
||||||
ws_.set_option(
|
|
||||||
websocket::stream_base::suggested_settings(
|
|
||||||
websocket::role_type::server));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
websocket_session::
|
websocket_session::
|
||||||
|
@ -57,6 +57,20 @@ void
|
|||||||
websocket_session::
|
websocket_session::
|
||||||
run(http::request<Body, http::basic_fields<Allocator>> req)
|
run(http::request<Body, http::basic_fields<Allocator>> req)
|
||||||
{
|
{
|
||||||
|
// Set suggested timeout settings for the websocket
|
||||||
|
ws_.set_option(
|
||||||
|
websocket::stream_base::suggested_settings(
|
||||||
|
websocket::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-chat-multi");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws_.async_accept(
|
ws_.async_accept(
|
||||||
req,
|
req,
|
||||||
|
@ -75,6 +75,15 @@ do_session(
|
|||||||
websocket::stream_base::suggested_settings(
|
websocket::stream_base::suggested_settings(
|
||||||
websocket::role_type::server));
|
websocket::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-server-coro-ssl");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws.async_accept(yield[ec]);
|
ws.async_accept(yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
|
@ -56,6 +56,15 @@ do_session(ws_type& ws, net::yield_context yield)
|
|||||||
websocket::stream_base::suggested_settings(
|
websocket::stream_base::suggested_settings(
|
||||||
websocket::role_type::server));
|
websocket::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-server-coro");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws.async_accept(yield[ec]);
|
ws.async_accept(yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
|
@ -90,13 +90,15 @@ do_sync_session(ws_type& ws)
|
|||||||
|
|
||||||
setup_stream(ws);
|
setup_stream(ws);
|
||||||
|
|
||||||
ws.accept_ex(
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
[](websocket::response_type& res)
|
[](websocket::response_type& res)
|
||||||
{
|
{
|
||||||
res.set(http::field::server,
|
res.set(http::field::server, std::string(
|
||||||
"Boost.Beast/" + std::to_string(BOOST_BEAST_VERSION) + "-Sync");
|
BOOST_BEAST_VERSION_STRING) + "-Sync");
|
||||||
},
|
}));
|
||||||
ec);
|
|
||||||
|
ws.accept(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "accept");
|
return fail(ec, "accept");
|
||||||
|
|
||||||
@ -158,13 +160,16 @@ public:
|
|||||||
void
|
void
|
||||||
run()
|
run()
|
||||||
{
|
{
|
||||||
// Accept the websocket handshake
|
// Set a decorator to change the Server of the handshake
|
||||||
ws_.async_accept_ex(
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
[](websocket::response_type& res)
|
[](websocket::response_type& res)
|
||||||
{
|
{
|
||||||
res.set(http::field::server,
|
res.set(http::field::server, std::string(
|
||||||
"Boost.Beast/" + std::to_string(BOOST_BEAST_VERSION) + "-Async");
|
BOOST_BEAST_VERSION_STRING) + "-Async");
|
||||||
},
|
}));
|
||||||
|
|
||||||
|
// Accept the websocket handshake
|
||||||
|
ws_.async_accept(
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&async_session::on_accept,
|
&async_session::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
@ -324,13 +329,15 @@ do_coro_session(ws_type& ws, net::yield_context yield)
|
|||||||
|
|
||||||
setup_stream(ws);
|
setup_stream(ws);
|
||||||
|
|
||||||
ws.async_accept_ex(
|
// Set a decorator to change the Server of the handshake
|
||||||
[&](websocket::response_type& res)
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
{
|
{
|
||||||
res.set(http::field::server,
|
res.set(http::field::server, std::string(
|
||||||
"Boost.Beast/" + std::to_string(BOOST_BEAST_VERSION) + "-Coro");
|
BOOST_BEAST_VERSION_STRING) + "-Fiber");
|
||||||
},
|
}));
|
||||||
yield[ec]);
|
|
||||||
|
ws.async_accept(yield[ec]);
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "accept");
|
return fail(ec, "accept");
|
||||||
|
|
||||||
|
@ -102,6 +102,15 @@ public:
|
|||||||
websocket::stream_base::suggested_settings(
|
websocket::stream_base::suggested_settings(
|
||||||
websocket::role_type::server));
|
websocket::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-server-stackless-ssl");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
yield ws_.async_accept(
|
yield ws_.async_accept(
|
||||||
std::bind(
|
std::bind(
|
||||||
|
@ -79,6 +79,15 @@ public:
|
|||||||
websocket::stream_base::suggested_settings(
|
websocket::stream_base::suggested_settings(
|
||||||
websocket::role_type::server));
|
websocket::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-server-stackless");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
yield ws_.async_accept(
|
yield ws_.async_accept(
|
||||||
std::bind(
|
std::bind(
|
||||||
|
@ -48,6 +48,15 @@ do_session(tcp::socket& socket, ssl::context& ctx)
|
|||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
ws.next_layer().handshake(ssl::stream_base::server);
|
ws.next_layer().handshake(ssl::stream_base::server);
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-server-sync-ssl");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws.accept();
|
ws.accept();
|
||||||
|
|
||||||
|
@ -39,6 +39,15 @@ do_session(tcp::socket& socket)
|
|||||||
// Construct the stream by moving in the socket
|
// Construct the stream by moving in the socket
|
||||||
websocket::stream<tcp::socket> ws{std::move(socket)};
|
websocket::stream<tcp::socket> ws{std::move(socket)};
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
|
[](websocket::response_type& res)
|
||||||
|
{
|
||||||
|
res.set(http::field::server,
|
||||||
|
std::string(BOOST_BEAST_VERSION_STRING) +
|
||||||
|
" websocket-server-sync");
|
||||||
|
}));
|
||||||
|
|
||||||
// Accept the websocket handshake
|
// Accept the websocket handshake
|
||||||
ws.accept();
|
ws.accept();
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ public:
|
|||||||
void
|
void
|
||||||
reset() noexcept
|
reset() noexcept
|
||||||
{
|
{
|
||||||
static_assert(sizeof(I) != 0,
|
static_assert(I != 0,
|
||||||
BOOST_BEAST_DEPRECATION_STRING);
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@ -37,14 +38,12 @@ class decorator
|
|||||||
void(*)(),
|
void(*)(),
|
||||||
void(incomplete::*)(),
|
void(incomplete::*)(),
|
||||||
decltype(std::bind(
|
decltype(std::bind(
|
||||||
std::declval<void(incomplete::*)()>(),
|
std::declval<
|
||||||
std::declval<std::shared_ptr<incomplete>>()))
|
void(incomplete::*)(request_type&)>(),
|
||||||
|
std::shared_ptr<incomplete>{},
|
||||||
|
std::placeholders::_1))
|
||||||
>();
|
>();
|
||||||
|
|
||||||
struct none
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct base
|
struct base
|
||||||
{
|
{
|
||||||
virtual ~base() = default;
|
virtual ~base() = default;
|
||||||
@ -62,6 +61,16 @@ class decorator
|
|||||||
invoke(response_type&) = 0;
|
invoke(response_type&) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using type = typename
|
||||||
|
std::aligned_storage<Bytes>::type;
|
||||||
|
|
||||||
|
type buf_;
|
||||||
|
base* base_;
|
||||||
|
|
||||||
|
struct none
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template<class T, class = void>
|
template<class T, class = void>
|
||||||
struct is_req_op : std::false_type
|
struct is_req_op : std::false_type
|
||||||
{
|
{
|
||||||
@ -143,13 +152,42 @@ class decorator
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using type = typename
|
void
|
||||||
std::aligned_storage<Bytes>::type;
|
destroy()
|
||||||
|
{
|
||||||
|
if(is_inline())
|
||||||
|
base_->~base();
|
||||||
|
else if(base_)
|
||||||
|
delete base_;
|
||||||
|
}
|
||||||
|
|
||||||
type buf_;
|
template<class F>
|
||||||
base* base_;
|
base*
|
||||||
|
construct(F&& f, std::true_type)
|
||||||
|
{
|
||||||
|
return ::new(&buf_) impl<
|
||||||
|
typename std::decay<F>::type>(
|
||||||
|
std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
base*
|
||||||
|
construct(F&& f, std::false_type)
|
||||||
|
{
|
||||||
|
return new impl<
|
||||||
|
typename std::decay<F>::type>(
|
||||||
|
std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
decorator(decorator const&) = delete;
|
||||||
|
decorator& operator=(decorator const&) = delete;
|
||||||
|
|
||||||
|
~decorator()
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
decorator()
|
decorator()
|
||||||
: decorator(none{})
|
: decorator(none{})
|
||||||
{
|
{
|
||||||
@ -171,25 +209,34 @@ public:
|
|||||||
impl<none>(none{});
|
impl<none>(none{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class F>
|
template<class F,
|
||||||
|
class = typename std::enable_if<
|
||||||
|
! std::is_convertible<F, decorator>::value>::type>
|
||||||
explicit
|
explicit
|
||||||
decorator(F&& f)
|
decorator(F&& f)
|
||||||
: base_(sizeof(F) <= sizeof(buf_) ?
|
: base_(construct(std::forward<F>(f),
|
||||||
::new(&buf_) impl<
|
std::integral_constant<bool,
|
||||||
typename std::decay<F>::type>(
|
sizeof(F) <= sizeof(buf_)>{}))
|
||||||
std::forward<F>(f)) :
|
|
||||||
new impl<
|
|
||||||
typename std::decay<F>::type>(
|
|
||||||
std::forward<F>(f)))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~decorator()
|
decorator&
|
||||||
|
operator=(decorator&& other)
|
||||||
{
|
{
|
||||||
if(is_inline())
|
this->destroy();
|
||||||
base_->~base();
|
base_ = nullptr;
|
||||||
|
if(other.is_inline())
|
||||||
|
{
|
||||||
|
base_ = other.base_->move(&buf_);
|
||||||
|
other.base_->~base();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
delete base_;
|
{
|
||||||
|
base_ = other.base_;
|
||||||
|
}
|
||||||
|
other.base_ = ::new(&other.buf_)
|
||||||
|
impl<none>(none{});
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -75,12 +75,15 @@ build_response(
|
|||||||
error_code& result)
|
error_code& result)
|
||||||
{
|
{
|
||||||
auto const decorate =
|
auto const decorate =
|
||||||
[&decorator](response_type& res)
|
[this, &decorator](response_type& res)
|
||||||
{
|
{
|
||||||
|
decorator_opt(res);
|
||||||
decorator(res);
|
decorator(res);
|
||||||
if(! res.count(http::field::server))
|
if(! res.count(http::field::server))
|
||||||
{
|
{
|
||||||
BOOST_STATIC_ASSERT(sizeof(BOOST_BEAST_VERSION_STRING) < 20);
|
// VFALCO this is weird..
|
||||||
|
BOOST_STATIC_ASSERT(sizeof(
|
||||||
|
BOOST_BEAST_VERSION_STRING) < 20);
|
||||||
static_string<20> s(BOOST_BEAST_VERSION_STRING);
|
static_string<20> s(BOOST_BEAST_VERSION_STRING);
|
||||||
res.set(http::field::server, s);
|
res.set(http::field::server, s);
|
||||||
}
|
}
|
||||||
@ -395,23 +398,6 @@ accept()
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<class ResponseDecorator>
|
|
||||||
void
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
accept_ex(ResponseDecorator const& decorator)
|
|
||||||
{
|
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
|
||||||
"SyncStream requirements not met");
|
|
||||||
static_assert(detail::is_response_decorator<
|
|
||||||
ResponseDecorator>::value,
|
|
||||||
"ResponseDecorator requirements not met");
|
|
||||||
error_code ec;
|
|
||||||
accept_ex(decorator, ec);
|
|
||||||
if(ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer, deflateSupported>::
|
stream<NextLayer, deflateSupported>::
|
||||||
@ -424,22 +410,6 @@ accept(error_code& ec)
|
|||||||
&default_decorate_res, ec);
|
&default_decorate_res, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<class ResponseDecorator>
|
|
||||||
void
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
accept_ex(ResponseDecorator const& decorator, error_code& ec)
|
|
||||||
{
|
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
|
||||||
"SyncStream requirements not met");
|
|
||||||
static_assert(detail::is_response_decorator<
|
|
||||||
ResponseDecorator>::value,
|
|
||||||
"ResponseDecorator requirements not met");
|
|
||||||
do_accept(
|
|
||||||
net::const_buffer{},
|
|
||||||
decorator, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
typename std::enable_if<! http::detail::is_header<
|
typename std::enable_if<! http::detail::is_header<
|
||||||
@ -457,32 +427,6 @@ accept(ConstBufferSequence const& buffers)
|
|||||||
if(ec)
|
if(ec)
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<
|
|
||||||
class ConstBufferSequence,
|
|
||||||
class ResponseDecorator>
|
|
||||||
typename std::enable_if<! http::detail::is_header<
|
|
||||||
ConstBufferSequence>::value>::type
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
accept_ex(
|
|
||||||
ConstBufferSequence const& buffers,
|
|
||||||
ResponseDecorator const &decorator)
|
|
||||||
{
|
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
|
||||||
"SyncStream requirements not met");
|
|
||||||
static_assert(net::is_const_buffer_sequence<
|
|
||||||
ConstBufferSequence>::value,
|
|
||||||
"ConstBufferSequence requirements not met");
|
|
||||||
static_assert(detail::is_response_decorator<
|
|
||||||
ResponseDecorator>::value,
|
|
||||||
"ResponseDecorator requirements not met");
|
|
||||||
error_code ec;
|
|
||||||
accept_ex(buffers, decorator, ec);
|
|
||||||
if(ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
typename std::enable_if<! http::detail::is_header<
|
typename std::enable_if<! http::detail::is_header<
|
||||||
@ -499,28 +443,6 @@ accept(
|
|||||||
do_accept(buffers, &default_decorate_res, ec);
|
do_accept(buffers, &default_decorate_res, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<
|
|
||||||
class ConstBufferSequence,
|
|
||||||
class ResponseDecorator>
|
|
||||||
typename std::enable_if<! http::detail::is_header<
|
|
||||||
ConstBufferSequence>::value>::type
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
accept_ex(
|
|
||||||
ConstBufferSequence const& buffers,
|
|
||||||
ResponseDecorator const& decorator,
|
|
||||||
error_code& ec)
|
|
||||||
{
|
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
|
||||||
"SyncStream requirements not met");
|
|
||||||
static_assert(net::is_const_buffer_sequence<
|
|
||||||
ConstBufferSequence>::value,
|
|
||||||
"ConstBufferSequence requirements not met");
|
|
||||||
static_assert(net::is_const_buffer_sequence<
|
|
||||||
ConstBufferSequence>::value,
|
|
||||||
"ConstBufferSequence requirements not met");
|
|
||||||
do_accept(buffers, decorator, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
@ -538,28 +460,6 @@ accept(
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<
|
|
||||||
class Body, class Allocator,
|
|
||||||
class ResponseDecorator>
|
|
||||||
void
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
accept_ex(
|
|
||||||
http::request<Body,
|
|
||||||
http::basic_fields<Allocator>> const& req,
|
|
||||||
ResponseDecorator const& decorator)
|
|
||||||
{
|
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
|
||||||
"SyncStream requirements not met");
|
|
||||||
static_assert(detail::is_response_decorator<
|
|
||||||
ResponseDecorator>::value,
|
|
||||||
"ResponseDecorator requirements not met");
|
|
||||||
error_code ec;
|
|
||||||
accept_ex(req, decorator, ec);
|
|
||||||
if(ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
void
|
void
|
||||||
@ -575,27 +475,6 @@ accept(
|
|||||||
do_accept(req, &default_decorate_res, ec);
|
do_accept(req, &default_decorate_res, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<
|
|
||||||
class Body, class Allocator,
|
|
||||||
class ResponseDecorator>
|
|
||||||
void
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
accept_ex(
|
|
||||||
http::request<Body,
|
|
||||||
http::basic_fields<Allocator>> const& req,
|
|
||||||
ResponseDecorator const& decorator,
|
|
||||||
error_code& ec)
|
|
||||||
{
|
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
|
||||||
"SyncStream requirements not met");
|
|
||||||
static_assert(detail::is_response_decorator<
|
|
||||||
ResponseDecorator>::value,
|
|
||||||
"ResponseDecorator requirements not met");
|
|
||||||
impl_->reset();
|
|
||||||
do_accept(req, decorator, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
@ -769,6 +648,156 @@ async_accept_ex(
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<class ResponseDecorator>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
accept_ex(ResponseDecorator const& decorator)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(ResponseDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
|
"SyncStream requirements not met");
|
||||||
|
static_assert(detail::is_response_decorator<
|
||||||
|
ResponseDecorator>::value,
|
||||||
|
"ResponseDecorator requirements not met");
|
||||||
|
error_code ec;
|
||||||
|
accept_ex(decorator, ec);
|
||||||
|
if(ec)
|
||||||
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<class ResponseDecorator>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
accept_ex(ResponseDecorator const& decorator, error_code& ec)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(ResponseDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
|
"SyncStream requirements not met");
|
||||||
|
static_assert(detail::is_response_decorator<
|
||||||
|
ResponseDecorator>::value,
|
||||||
|
"ResponseDecorator requirements not met");
|
||||||
|
do_accept(
|
||||||
|
net::const_buffer{},
|
||||||
|
decorator, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<
|
||||||
|
class ConstBufferSequence,
|
||||||
|
class ResponseDecorator>
|
||||||
|
typename std::enable_if<! http::detail::is_header<
|
||||||
|
ConstBufferSequence>::value>::type
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
accept_ex(
|
||||||
|
ConstBufferSequence const& buffers,
|
||||||
|
ResponseDecorator const &decorator)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(ResponseDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
|
"SyncStream requirements not met");
|
||||||
|
static_assert(net::is_const_buffer_sequence<
|
||||||
|
ConstBufferSequence>::value,
|
||||||
|
"ConstBufferSequence requirements not met");
|
||||||
|
static_assert(detail::is_response_decorator<
|
||||||
|
ResponseDecorator>::value,
|
||||||
|
"ResponseDecorator requirements not met");
|
||||||
|
error_code ec;
|
||||||
|
accept_ex(buffers, decorator, ec);
|
||||||
|
if(ec)
|
||||||
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<
|
||||||
|
class ConstBufferSequence,
|
||||||
|
class ResponseDecorator>
|
||||||
|
typename std::enable_if<! http::detail::is_header<
|
||||||
|
ConstBufferSequence>::value>::type
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
accept_ex(
|
||||||
|
ConstBufferSequence const& buffers,
|
||||||
|
ResponseDecorator const& decorator,
|
||||||
|
error_code& ec)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(ResponseDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
|
"SyncStream requirements not met");
|
||||||
|
static_assert(net::is_const_buffer_sequence<
|
||||||
|
ConstBufferSequence>::value,
|
||||||
|
"ConstBufferSequence requirements not met");
|
||||||
|
static_assert(net::is_const_buffer_sequence<
|
||||||
|
ConstBufferSequence>::value,
|
||||||
|
"ConstBufferSequence requirements not met");
|
||||||
|
do_accept(buffers, decorator, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<
|
||||||
|
class Body, class Allocator,
|
||||||
|
class ResponseDecorator>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
accept_ex(
|
||||||
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
ResponseDecorator const& decorator)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(ResponseDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
|
"SyncStream requirements not met");
|
||||||
|
static_assert(detail::is_response_decorator<
|
||||||
|
ResponseDecorator>::value,
|
||||||
|
"ResponseDecorator requirements not met");
|
||||||
|
error_code ec;
|
||||||
|
accept_ex(req, decorator, ec);
|
||||||
|
if(ec)
|
||||||
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<
|
||||||
|
class Body, class Allocator,
|
||||||
|
class ResponseDecorator>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
accept_ex(
|
||||||
|
http::request<Body,
|
||||||
|
http::basic_fields<Allocator>> const& req,
|
||||||
|
ResponseDecorator const& decorator,
|
||||||
|
error_code& ec)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(ResponseDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
|
"SyncStream requirements not met");
|
||||||
|
static_assert(detail::is_response_decorator<
|
||||||
|
ResponseDecorator>::value,
|
||||||
|
"ResponseDecorator requirements not met");
|
||||||
|
impl_->reset();
|
||||||
|
do_accept(req, decorator, ec);
|
||||||
|
}
|
||||||
|
|
||||||
} // websocket
|
} // websocket
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
@ -195,57 +195,6 @@ async_handshake(response_type& res,
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<class RequestDecorator, class HandshakeHandler>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
|
||||||
HandshakeHandler, void(error_code))
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
async_handshake_ex(string_view host,
|
|
||||||
string_view target,
|
|
||||||
RequestDecorator const& decorator,
|
|
||||||
HandshakeHandler&& handler)
|
|
||||||
{
|
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
|
||||||
"AsyncStream requirements not met");
|
|
||||||
static_assert(detail::is_request_decorator<
|
|
||||||
RequestDecorator>::value,
|
|
||||||
"RequestDecorator requirements not met");
|
|
||||||
BOOST_BEAST_HANDLER_INIT(
|
|
||||||
HandshakeHandler, void(error_code));
|
|
||||||
handshake_op<BOOST_ASIO_HANDLER_TYPE(
|
|
||||||
HandshakeHandler, void(error_code))>(
|
|
||||||
std::move(init.completion_handler),
|
|
||||||
impl_, nullptr, host, target,
|
|
||||||
decorator)();
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<class RequestDecorator, class HandshakeHandler>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
|
||||||
HandshakeHandler, void(error_code))
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
async_handshake_ex(response_type& res,
|
|
||||||
string_view host,
|
|
||||||
string_view target,
|
|
||||||
RequestDecorator const& decorator,
|
|
||||||
HandshakeHandler&& handler)
|
|
||||||
{
|
|
||||||
static_assert(is_async_stream<next_layer_type>::value,
|
|
||||||
"AsyncStream requirements not met");
|
|
||||||
static_assert(detail::is_request_decorator<
|
|
||||||
RequestDecorator>::value,
|
|
||||||
"RequestDecorator requirements not met");
|
|
||||||
BOOST_BEAST_HANDLER_INIT(
|
|
||||||
HandshakeHandler, void(error_code));
|
|
||||||
handshake_op<BOOST_ASIO_HANDLER_TYPE(
|
|
||||||
HandshakeHandler, void(error_code))>(
|
|
||||||
std::move(init.completion_handler),
|
|
||||||
impl_, &res, host, target,
|
|
||||||
decorator)();
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer, deflateSupported>::
|
stream<NextLayer, deflateSupported>::
|
||||||
@ -276,45 +225,6 @@ handshake(response_type& res,
|
|||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<class RequestDecorator>
|
|
||||||
void
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
handshake_ex(string_view host,
|
|
||||||
string_view target,
|
|
||||||
RequestDecorator const& decorator)
|
|
||||||
{
|
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
|
||||||
"SyncStream requirements not met");
|
|
||||||
static_assert(detail::is_request_decorator<
|
|
||||||
RequestDecorator>::value,
|
|
||||||
"RequestDecorator requirements not met");
|
|
||||||
error_code ec;
|
|
||||||
handshake_ex(host, target, decorator, ec);
|
|
||||||
if(ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
|
||||||
template<class RequestDecorator>
|
|
||||||
void
|
|
||||||
stream<NextLayer, deflateSupported>::
|
|
||||||
handshake_ex(response_type& res,
|
|
||||||
string_view host,
|
|
||||||
string_view target,
|
|
||||||
RequestDecorator const& decorator)
|
|
||||||
{
|
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
|
||||||
"SyncStream requirements not met");
|
|
||||||
static_assert(detail::is_request_decorator<
|
|
||||||
RequestDecorator>::value,
|
|
||||||
"RequestDecorator requirements not met");
|
|
||||||
error_code ec;
|
|
||||||
handshake_ex(res, host, target, decorator, ec);
|
|
||||||
if(ec)
|
|
||||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
void
|
void
|
||||||
stream<NextLayer, deflateSupported>::
|
stream<NextLayer, deflateSupported>::
|
||||||
@ -341,6 +251,55 @@ handshake(response_type& res,
|
|||||||
host, target, &default_decorate_req, ec);
|
host, target, &default_decorate_req, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<class RequestDecorator>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
handshake_ex(string_view host,
|
||||||
|
string_view target,
|
||||||
|
RequestDecorator const& decorator)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(RequestDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
|
"SyncStream requirements not met");
|
||||||
|
static_assert(detail::is_request_decorator<
|
||||||
|
RequestDecorator>::value,
|
||||||
|
"RequestDecorator requirements not met");
|
||||||
|
error_code ec;
|
||||||
|
handshake_ex(host, target, decorator, ec);
|
||||||
|
if(ec)
|
||||||
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<class RequestDecorator>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
handshake_ex(response_type& res,
|
||||||
|
string_view host,
|
||||||
|
string_view target,
|
||||||
|
RequestDecorator const& decorator)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(RequestDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
|
"SyncStream requirements not met");
|
||||||
|
static_assert(detail::is_request_decorator<
|
||||||
|
RequestDecorator>::value,
|
||||||
|
"RequestDecorator requirements not met");
|
||||||
|
error_code ec;
|
||||||
|
handshake_ex(res, host, target, decorator, ec);
|
||||||
|
if(ec)
|
||||||
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class RequestDecorator>
|
template<class RequestDecorator>
|
||||||
void
|
void
|
||||||
@ -350,6 +309,10 @@ handshake_ex(string_view host,
|
|||||||
RequestDecorator const& decorator,
|
RequestDecorator const& decorator,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(RequestDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_request_decorator<
|
static_assert(detail::is_request_decorator<
|
||||||
@ -369,6 +332,10 @@ handshake_ex(response_type& res,
|
|||||||
RequestDecorator const& decorator,
|
RequestDecorator const& decorator,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(RequestDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
static_assert(is_sync_stream<next_layer_type>::value,
|
static_assert(is_sync_stream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
static_assert(detail::is_request_decorator<
|
static_assert(detail::is_request_decorator<
|
||||||
@ -378,6 +345,68 @@ handshake_ex(response_type& res,
|
|||||||
host, target, decorator, ec);
|
host, target, decorator, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<class RequestDecorator, class HandshakeHandler>
|
||||||
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
|
HandshakeHandler, void(error_code))
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
async_handshake_ex(string_view host,
|
||||||
|
string_view target,
|
||||||
|
RequestDecorator const& decorator,
|
||||||
|
HandshakeHandler&& handler)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(RequestDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
|
"AsyncStream requirements not met");
|
||||||
|
static_assert(detail::is_request_decorator<
|
||||||
|
RequestDecorator>::value,
|
||||||
|
"RequestDecorator requirements not met");
|
||||||
|
BOOST_BEAST_HANDLER_INIT(
|
||||||
|
HandshakeHandler, void(error_code));
|
||||||
|
handshake_op<BOOST_ASIO_HANDLER_TYPE(
|
||||||
|
HandshakeHandler, void(error_code))>(
|
||||||
|
std::move(init.completion_handler),
|
||||||
|
impl_, nullptr, host, target,
|
||||||
|
decorator)();
|
||||||
|
return init.result.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
template<class RequestDecorator, class HandshakeHandler>
|
||||||
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
|
HandshakeHandler, void(error_code))
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
async_handshake_ex(response_type& res,
|
||||||
|
string_view host,
|
||||||
|
string_view target,
|
||||||
|
RequestDecorator const& decorator,
|
||||||
|
HandshakeHandler&& handler)
|
||||||
|
{
|
||||||
|
#if ! BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
static_assert(sizeof(RequestDecorator) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
static_assert(is_async_stream<next_layer_type>::value,
|
||||||
|
"AsyncStream requirements not met");
|
||||||
|
static_assert(detail::is_request_decorator<
|
||||||
|
RequestDecorator>::value,
|
||||||
|
"RequestDecorator requirements not met");
|
||||||
|
BOOST_BEAST_HANDLER_INIT(
|
||||||
|
HandshakeHandler, void(error_code));
|
||||||
|
handshake_op<BOOST_ASIO_HANDLER_TYPE(
|
||||||
|
HandshakeHandler, void(error_code))>(
|
||||||
|
std::move(init.completion_handler),
|
||||||
|
impl_, &res, host, target,
|
||||||
|
decorator)();
|
||||||
|
return init.result.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // websocket
|
} // websocket
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
@ -147,6 +147,16 @@ read_size_hint(DynamicBuffer& buffer) const
|
|||||||
//
|
//
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// decorator
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
void
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
set_option(decorator opt)
|
||||||
|
{
|
||||||
|
impl_->decorator_opt = std::move(opt.d_);
|
||||||
|
}
|
||||||
|
|
||||||
// timeout
|
// timeout
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
@ -96,7 +96,8 @@ struct stream<NextLayer, deflateSupported>::impl_type
|
|||||||
bool timed_out = false;
|
bool timed_out = false;
|
||||||
int idle_counter = 0;
|
int idle_counter = 0;
|
||||||
|
|
||||||
timeout timeout_opt;
|
detail::decorator decorator_opt; // Decorator for HTTP messages
|
||||||
|
timeout timeout_opt; // Timeout/idle settings
|
||||||
|
|
||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
@ -532,6 +533,7 @@ build_request(
|
|||||||
req.set(http::field::sec_websocket_key, key);
|
req.set(http::field::sec_websocket_key, key);
|
||||||
req.set(http::field::sec_websocket_version, "13");
|
req.set(http::field::sec_websocket_version, "13");
|
||||||
this->build_request_pmd(req);
|
this->build_request_pmd(req);
|
||||||
|
decorator_opt(req);
|
||||||
decorator(req);
|
decorator(req);
|
||||||
if(! req.count(http::field::user_agent))
|
if(! req.count(http::field::user_agent))
|
||||||
req.set(http::field::user_agent,
|
req.set(http::field::user_agent,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
#include <boost/beast/websocket/role.hpp>
|
#include <boost/beast/websocket/role.hpp>
|
||||||
|
#include <boost/beast/websocket/detail/decorator.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@ -48,6 +49,25 @@ struct stream_base
|
|||||||
return (duration::max)();
|
return (duration::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Stream option used to adjust HTTP fields of WebSocket upgrade request and responses.
|
||||||
|
*/
|
||||||
|
class decorator
|
||||||
|
{
|
||||||
|
detail::decorator d_;
|
||||||
|
|
||||||
|
template<class, bool>
|
||||||
|
friend class stream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
decorator(decorator&&) = default;
|
||||||
|
|
||||||
|
template<class Decorator>
|
||||||
|
decorator(Decorator&& f)
|
||||||
|
: d_(f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** Stream option to control the behavior of websocket timeouts.
|
/** Stream option to control the behavior of websocket timeouts.
|
||||||
|
|
||||||
Timeout features are available for asynchronous operations only.
|
Timeout features are available for asynchronous operations only.
|
||||||
|
@ -70,10 +70,13 @@ public:
|
|||||||
|
|
||||||
struct both_t : res_t , req_t
|
struct both_t : res_t , req_t
|
||||||
{
|
{
|
||||||
|
using req_t::operator();
|
||||||
|
using res_t::operator();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct big_t : both_t
|
struct big_t : both_t
|
||||||
{
|
{
|
||||||
|
using both_t::operator();
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -109,11 +112,15 @@ public:
|
|||||||
decorator d1{req_t{}};
|
decorator d1{req_t{}};
|
||||||
decorator d2{std::move(d1)};
|
decorator d2{std::move(d1)};
|
||||||
d2(req);
|
d2(req);
|
||||||
|
decorator d3;
|
||||||
|
d3 = std::move(d2);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// this would be leaner with bind_front
|
||||||
decorator d(std::bind(
|
decorator d(std::bind(
|
||||||
&decorator_test::dec_req, this));
|
&decorator_test::dec_req, this,
|
||||||
|
std::placeholders::_1));
|
||||||
BEAST_EXPECT(d.is_inline());
|
BEAST_EXPECT(d.is_inline());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,6 +128,7 @@ public:
|
|||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
|
log << "sizeof(decorator)==" << sizeof(decorator) << "\n";
|
||||||
testDecorator();
|
testDecorator();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -28,6 +28,20 @@ public:
|
|||||||
net::io_context ioc;
|
net::io_context ioc;
|
||||||
stream<test::stream> ws(ioc);
|
stream<test::stream> ws(ioc);
|
||||||
|
|
||||||
|
{
|
||||||
|
ws.set_option(
|
||||||
|
stream_base::decorator(
|
||||||
|
[](request_type&)
|
||||||
|
{
|
||||||
|
}));
|
||||||
|
|
||||||
|
ws.set_option(
|
||||||
|
stream_base::decorator(
|
||||||
|
[](response_type&)
|
||||||
|
{
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ws.set_option(
|
ws.set_option(
|
||||||
stream_base::suggested_settings(
|
stream_base::suggested_settings(
|
||||||
|
@ -25,6 +25,7 @@ add_executable (tests-doc
|
|||||||
core_3_layers.cpp
|
core_3_layers.cpp
|
||||||
http_examples.cpp
|
http_examples.cpp
|
||||||
http_snippets.cpp
|
http_snippets.cpp
|
||||||
|
websocket_3_handshake.cpp
|
||||||
websocket_snippets.cpp
|
websocket_snippets.cpp
|
||||||
exemplars.cpp
|
exemplars.cpp
|
||||||
)
|
)
|
||||||
|
@ -23,6 +23,7 @@ alias run-tests :
|
|||||||
[ run core_1_refresher.cpp $(TEST_MAIN) ]
|
[ run core_1_refresher.cpp $(TEST_MAIN) ]
|
||||||
[ run core_3_layers.cpp $(TEST_MAIN) ]
|
[ run core_3_layers.cpp $(TEST_MAIN) ]
|
||||||
[ run http_examples.cpp $(TEST_MAIN) ]
|
[ run http_examples.cpp $(TEST_MAIN) ]
|
||||||
|
[ run websocket_3_handshake.cpp $(TEST_MAIN) ]
|
||||||
;
|
;
|
||||||
|
|
||||||
exe fat-tests :
|
exe fat-tests :
|
||||||
@ -31,6 +32,7 @@ exe fat-tests :
|
|||||||
core_1_refresher.cpp
|
core_1_refresher.cpp
|
||||||
core_3_layers.cpp
|
core_3_layers.cpp
|
||||||
http_examples.cpp
|
http_examples.cpp
|
||||||
|
websocket_3_handshake.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
explicit fat-tests ;
|
explicit fat-tests ;
|
||||||
|
236
test/doc/websocket_3_handshake.cpp
Normal file
236
test/doc/websocket_3_handshake.cpp
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2016-2017 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)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "snippets.hpp"
|
||||||
|
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/beast/_experimental/test/stream.hpp>
|
||||||
|
#include <boost/beast/core/async_op_base.hpp>
|
||||||
|
#include <boost/beast/core/error.hpp>
|
||||||
|
#include <boost/beast/core/stream_traits.hpp>
|
||||||
|
#include <boost/beast/websocket.hpp>
|
||||||
|
#include <boost/asio/async_result.hpp>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace websocket {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void
|
||||||
|
websocket_3_handshake_snippets()
|
||||||
|
{
|
||||||
|
#include "snippets.ipp"
|
||||||
|
stream<net::ip::tcp::socket> ws(ioc);
|
||||||
|
{
|
||||||
|
//[code_websocket_3_client_1
|
||||||
|
|
||||||
|
// Note that the stream must already be connected, this
|
||||||
|
// function does not perform a DNS lookup on the host
|
||||||
|
// name, nor does it establish an outgoing connection.
|
||||||
|
|
||||||
|
// Perform the websocket handshake in the client role.
|
||||||
|
ws.handshake(
|
||||||
|
"www.example.com", // The Host field
|
||||||
|
"/", // The request-target
|
||||||
|
ec // Set to the error
|
||||||
|
);
|
||||||
|
|
||||||
|
//]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//[code_websocket_3_client_2
|
||||||
|
|
||||||
|
// Note that the stream must already be connected, this
|
||||||
|
// function does not perform a DNS lookup on the host
|
||||||
|
// name, nor does it establish an outgoing connection.
|
||||||
|
|
||||||
|
// This variable will receive the HTTP response from the server
|
||||||
|
response_type res;
|
||||||
|
|
||||||
|
// Perform the websocket handshake in the client role.
|
||||||
|
ws.handshake(
|
||||||
|
res, // Receives the HTTP response
|
||||||
|
"www.example.com", // The Host field
|
||||||
|
"/" // The request-target
|
||||||
|
,ec // Set to the error, if any
|
||||||
|
);
|
||||||
|
|
||||||
|
// Upon success, `res` will be set to the complete
|
||||||
|
// response received from the server.
|
||||||
|
//]
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{
|
||||||
|
//[code_websocket_3_server_1
|
||||||
|
|
||||||
|
// Note that the stream must already be connected
|
||||||
|
// to an incoming remote peer.
|
||||||
|
|
||||||
|
// Perform the websocket handshake in the server role.
|
||||||
|
ws.accept(
|
||||||
|
ec // Set to the error, if any
|
||||||
|
);
|
||||||
|
|
||||||
|
//]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//[code_websocket_3_server_2
|
||||||
|
// This buffer is required for reading HTTP messages
|
||||||
|
flat_buffer buffer;
|
||||||
|
|
||||||
|
// Read into our buffer until we reach the end of the HTTP request.
|
||||||
|
// No parsing takes place here, we are just accumulating data.
|
||||||
|
// We use beast::dynamic_buffer_ref to pass a lightweight, movable
|
||||||
|
// reference to our buffer, because Networking expects to take
|
||||||
|
// ownership unlike Beast algorithms which use a reference.
|
||||||
|
|
||||||
|
net::read_until(sock, dynamic_buffer_ref(buffer), "\r\n\r\n");
|
||||||
|
|
||||||
|
// Now accept the connection, using the buffered data.
|
||||||
|
ws.accept(buffer.data());
|
||||||
|
//]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
websocket_3_handshake_snippets_2()
|
||||||
|
{
|
||||||
|
using namespace boost::beast;
|
||||||
|
namespace net = boost::asio;
|
||||||
|
namespace ssl = boost::asio::ssl;
|
||||||
|
using tcp = net::ip::tcp;
|
||||||
|
error_code ec;
|
||||||
|
net::io_context ioc;
|
||||||
|
tcp::socket sock(ioc);
|
||||||
|
|
||||||
|
{
|
||||||
|
//[code_websocket_3_server_1b
|
||||||
|
// This buffer is required for reading HTTP messages
|
||||||
|
flat_buffer buffer;
|
||||||
|
|
||||||
|
// Read the HTTP request ourselves
|
||||||
|
http::request<http::string_body> req;
|
||||||
|
http::read(sock, buffer, req);
|
||||||
|
|
||||||
|
// See if its a WebSocket upgrade request
|
||||||
|
if(websocket::is_upgrade(req))
|
||||||
|
{
|
||||||
|
// Construct the stream, transferring ownership of the socket
|
||||||
|
stream<net::ip::tcp::socket> ws{std::move(sock)};
|
||||||
|
|
||||||
|
// Clients SHOULD NOT begin sending WebSocket
|
||||||
|
// frames until the server has provided a response.
|
||||||
|
BOOST_ASSERT(buffer.size() == 0);
|
||||||
|
|
||||||
|
// Accept the upgrade request
|
||||||
|
ws.accept(req);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Its not a WebSocket upgrade, so
|
||||||
|
// handle it like a normal HTTP request.
|
||||||
|
}
|
||||||
|
//]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//[code_websocket_3_decorator_1b
|
||||||
|
void set_user_agent(request_type& req)
|
||||||
|
{
|
||||||
|
// Set the User-Agent on the request
|
||||||
|
req.set(http::field::user_agent, "My User Agent");
|
||||||
|
}
|
||||||
|
//]
|
||||||
|
|
||||||
|
void
|
||||||
|
websocket_3_handshake_snippets_3()
|
||||||
|
{
|
||||||
|
#include "snippets.ipp"
|
||||||
|
stream<net::ip::tcp::socket> ws(ioc);
|
||||||
|
{
|
||||||
|
//[code_websocket_3_decorator_1
|
||||||
|
|
||||||
|
ws.set_option(stream_base::decorator(&set_user_agent));
|
||||||
|
|
||||||
|
//]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//[code_websocket_3_decorator_2
|
||||||
|
|
||||||
|
struct set_server
|
||||||
|
{
|
||||||
|
void operator()(response_type& res)
|
||||||
|
{
|
||||||
|
// Set the Server field on the response
|
||||||
|
res.set(http::field::user_agent, "My Server");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.set_option(stream_base::decorator(set_server{}));
|
||||||
|
|
||||||
|
//]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//[code_websocket_3_decorator_3
|
||||||
|
|
||||||
|
ws.set_option(stream_base::decorator(
|
||||||
|
[](response_type& res)
|
||||||
|
{
|
||||||
|
// Set the Server field on the response
|
||||||
|
res.set(http::field::user_agent, "My Server");
|
||||||
|
}));
|
||||||
|
|
||||||
|
//]
|
||||||
|
}
|
||||||
|
//[code_websocket_3_decorator_4
|
||||||
|
|
||||||
|
struct multi_decorator
|
||||||
|
{
|
||||||
|
void operator()(request_type& req)
|
||||||
|
{
|
||||||
|
// Set the User-Agent on the request
|
||||||
|
req.set(http::field::user_agent, "My User Agent");
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(response_type& res)
|
||||||
|
{
|
||||||
|
// Set the Server field on the response
|
||||||
|
res.set(http::field::user_agent, "My Server");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.set_option(stream_base::decorator(multi_decorator{}));
|
||||||
|
|
||||||
|
//]
|
||||||
|
}
|
||||||
|
|
||||||
|
} // (anon)
|
||||||
|
|
||||||
|
struct websocket_3_handshake_test
|
||||||
|
: public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
BEAST_EXPECT(&websocket_3_handshake_snippets);
|
||||||
|
BEAST_EXPECT(&websocket_3_handshake_snippets_2);
|
||||||
|
BEAST_EXPECT(&websocket_3_handshake_snippets_3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(beast,doc,websocket_3_handshake);
|
||||||
|
|
||||||
|
} // websocket
|
||||||
|
} // beast
|
||||||
|
} // boost
|
Reference in New Issue
Block a user