mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57:31 +02:00
Add const and non-const overloads for message based http writes:
fix #1113 This solves a problem where the message-oriented synchronous HTTP write algorithms do not support messages whose body writer requires a non-const reference to the message in order to construct. In addition, the message-oriented async_write algorithm is modified to support messages passed by const reference when possible, based on the body writer attributes.
This commit is contained in:
@ -9,6 +9,7 @@ Version 170:
|
|||||||
* Remove deprecated serializer::reader_impl()
|
* Remove deprecated serializer::reader_impl()
|
||||||
* Remove deprecated Body reader and writer ctor signatures
|
* Remove deprecated Body reader and writer ctor signatures
|
||||||
* Add is_mutable_body_writer metafunction
|
* Add is_mutable_body_writer metafunction
|
||||||
|
* Add const and non-const overloads for message based http writes
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -333,6 +333,14 @@ class write_msg_op
|
|||||||
, sr(m_)
|
, sr(m_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data(Handler const&, Stream& s_, message<
|
||||||
|
isRequest, Body, Fields> const& m_)
|
||||||
|
: s(s_)
|
||||||
|
, wg(s.get_executor())
|
||||||
|
, sr(m_)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handler_ptr<data, Handler> d_;
|
handler_ptr<data, Handler> d_;
|
||||||
@ -751,7 +759,33 @@ async_write(
|
|||||||
template<
|
template<
|
||||||
class SyncWriteStream,
|
class SyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields>
|
bool isRequest, class Body, class Fields>
|
||||||
std::size_t
|
typename std::enable_if<
|
||||||
|
is_mutable_body_writer<Body>::value,
|
||||||
|
std::size_t>::type
|
||||||
|
write(
|
||||||
|
SyncWriteStream& stream,
|
||||||
|
message<isRequest, Body, Fields>& msg)
|
||||||
|
{
|
||||||
|
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||||
|
"SyncWriteStream requirements not met");
|
||||||
|
static_assert(is_body<Body>::value,
|
||||||
|
"Body requirements not met");
|
||||||
|
static_assert(is_body_writer<Body>::value,
|
||||||
|
"BodyWriter requirements not met");
|
||||||
|
error_code ec;
|
||||||
|
auto const bytes_transferred =
|
||||||
|
write(stream, msg, ec);
|
||||||
|
if(ec)
|
||||||
|
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||||
|
return bytes_transferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
class SyncWriteStream,
|
||||||
|
bool isRequest, class Body, class Fields>
|
||||||
|
typename std::enable_if<
|
||||||
|
! is_mutable_body_writer<Body>::value,
|
||||||
|
std::size_t>::type
|
||||||
write(
|
write(
|
||||||
SyncWriteStream& stream,
|
SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Fields> const& msg)
|
message<isRequest, Body, Fields> const& msg)
|
||||||
@ -773,7 +807,30 @@ write(
|
|||||||
template<
|
template<
|
||||||
class SyncWriteStream,
|
class SyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields>
|
bool isRequest, class Body, class Fields>
|
||||||
std::size_t
|
typename std::enable_if<
|
||||||
|
is_mutable_body_writer<Body>::value,
|
||||||
|
std::size_t>::type
|
||||||
|
write(
|
||||||
|
SyncWriteStream& stream,
|
||||||
|
message<isRequest, Body, Fields>& msg,
|
||||||
|
error_code& ec)
|
||||||
|
{
|
||||||
|
static_assert(is_sync_write_stream<SyncWriteStream>::value,
|
||||||
|
"SyncWriteStream requirements not met");
|
||||||
|
static_assert(is_body<Body>::value,
|
||||||
|
"Body requirements not met");
|
||||||
|
static_assert(is_body_writer<Body>::value,
|
||||||
|
"BodyWriter requirements not met");
|
||||||
|
serializer<isRequest, Body, Fields> sr{msg};
|
||||||
|
return write(stream, sr, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
class SyncWriteStream,
|
||||||
|
bool isRequest, class Body, class Fields>
|
||||||
|
typename std::enable_if<
|
||||||
|
! is_mutable_body_writer<Body>::value,
|
||||||
|
std::size_t>::type
|
||||||
write(
|
write(
|
||||||
SyncWriteStream& stream,
|
SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Fields> const& msg,
|
message<isRequest, Body, Fields> const& msg,
|
||||||
@ -793,8 +850,10 @@ template<
|
|||||||
class AsyncWriteStream,
|
class AsyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields,
|
bool isRequest, class Body, class Fields,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
typename std::enable_if<
|
||||||
WriteHandler, void(error_code, std::size_t))
|
is_mutable_body_writer<Body>::value,
|
||||||
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
|
WriteHandler, void(error_code, std::size_t))>::type
|
||||||
async_write(
|
async_write(
|
||||||
AsyncWriteStream& stream,
|
AsyncWriteStream& stream,
|
||||||
message<isRequest, Body, Fields>& msg,
|
message<isRequest, Body, Fields>& msg,
|
||||||
@ -818,6 +877,37 @@ async_write(
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
class AsyncWriteStream,
|
||||||
|
bool isRequest, class Body, class Fields,
|
||||||
|
class WriteHandler>
|
||||||
|
typename std::enable_if<
|
||||||
|
! is_mutable_body_writer<Body>::value,
|
||||||
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
|
WriteHandler, void(error_code, std::size_t))>::type
|
||||||
|
async_write(
|
||||||
|
AsyncWriteStream& stream,
|
||||||
|
message<isRequest, Body, Fields> const& msg,
|
||||||
|
WriteHandler&& handler)
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
is_async_write_stream<AsyncWriteStream>::value,
|
||||||
|
"AsyncWriteStream requirements not met");
|
||||||
|
static_assert(is_body<Body>::value,
|
||||||
|
"Body requirements not met");
|
||||||
|
static_assert(is_body_writer<Body>::value,
|
||||||
|
"BodyWriter requirements not met");
|
||||||
|
BOOST_BEAST_HANDLER_INIT(
|
||||||
|
WriteHandler, void(error_code, std::size_t));
|
||||||
|
detail::write_msg_op<
|
||||||
|
AsyncWriteStream,
|
||||||
|
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||||
|
void(error_code, std::size_t)),
|
||||||
|
isRequest, Body, Fields>{
|
||||||
|
std::move(init.completion_handler), stream, msg}();
|
||||||
|
return init.result.get();
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <boost/beast/core/multi_buffer.hpp>
|
#include <boost/beast/core/multi_buffer.hpp>
|
||||||
#include <boost/beast/http/message.hpp>
|
#include <boost/beast/http/message.hpp>
|
||||||
#include <boost/beast/http/serializer.hpp>
|
#include <boost/beast/http/serializer.hpp>
|
||||||
|
#include <boost/beast/http/type_traits.hpp>
|
||||||
#include <boost/beast/http/detail/chunk_encode.hpp>
|
#include <boost/beast/http/detail/chunk_encode.hpp>
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
@ -427,6 +428,9 @@ async_write(
|
|||||||
`write_some` function. The algorithm will use a temporary @ref serializer
|
`write_some` function. The algorithm will use a temporary @ref serializer
|
||||||
with an empty chunk decorator to produce buffers.
|
with an empty chunk decorator to produce buffers.
|
||||||
|
|
||||||
|
@note This function only participates in overload resolution
|
||||||
|
if @ref is_mutable_body_writer for @b Body returns `true`.
|
||||||
|
|
||||||
@param stream The stream to which the data is to be written.
|
@param stream The stream to which the data is to be written.
|
||||||
The type must support the @b SyncWriteStream concept.
|
The type must support the @b SyncWriteStream concept.
|
||||||
|
|
||||||
@ -441,7 +445,54 @@ async_write(
|
|||||||
template<
|
template<
|
||||||
class SyncWriteStream,
|
class SyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields>
|
bool isRequest, class Body, class Fields>
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
std::size_t
|
std::size_t
|
||||||
|
#else
|
||||||
|
typename std::enable_if<
|
||||||
|
is_mutable_body_writer<Body>::value,
|
||||||
|
std::size_t>::type
|
||||||
|
#endif
|
||||||
|
write(
|
||||||
|
SyncWriteStream& stream,
|
||||||
|
message<isRequest, Body, Fields>& msg);
|
||||||
|
|
||||||
|
/** Write a complete message to a stream.
|
||||||
|
|
||||||
|
This function is used to write a complete message to a stream using
|
||||||
|
HTTP/1. The call will block until one of the following conditions is true:
|
||||||
|
|
||||||
|
@li The entire message is written.
|
||||||
|
|
||||||
|
@li An error occurs.
|
||||||
|
|
||||||
|
This operation is implemented in terms of one or more calls to the stream's
|
||||||
|
`write_some` function. The algorithm will use a temporary @ref serializer
|
||||||
|
with an empty chunk decorator to produce buffers.
|
||||||
|
|
||||||
|
@note This function only participates in overload resolution
|
||||||
|
if @ref is_mutable_body_writer for @b Body returns `false`.
|
||||||
|
|
||||||
|
@param stream The stream to which the data is to be written.
|
||||||
|
The type must support the @b SyncWriteStream concept.
|
||||||
|
|
||||||
|
@param msg The message to write.
|
||||||
|
|
||||||
|
@return The number of bytes written to the stream.
|
||||||
|
|
||||||
|
@throws system_error Thrown on failure.
|
||||||
|
|
||||||
|
@see @ref message
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
class SyncWriteStream,
|
||||||
|
bool isRequest, class Body, class Fields>
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
|
std::size_t
|
||||||
|
#else
|
||||||
|
typename std::enable_if<
|
||||||
|
! is_mutable_body_writer<Body>::value,
|
||||||
|
std::size_t>::type
|
||||||
|
#endif
|
||||||
write(
|
write(
|
||||||
SyncWriteStream& stream,
|
SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Fields> const& msg);
|
message<isRequest, Body, Fields> const& msg);
|
||||||
@ -459,6 +510,9 @@ write(
|
|||||||
`write_some` function. The algorithm will use a temporary @ref serializer
|
`write_some` function. The algorithm will use a temporary @ref serializer
|
||||||
with an empty chunk decorator to produce buffers.
|
with an empty chunk decorator to produce buffers.
|
||||||
|
|
||||||
|
@note This function only participates in overload resolution
|
||||||
|
if @ref is_mutable_body_writer for @b Body returns `true`.
|
||||||
|
|
||||||
@param stream The stream to which the data is to be written.
|
@param stream The stream to which the data is to be written.
|
||||||
The type must support the @b SyncWriteStream concept.
|
The type must support the @b SyncWriteStream concept.
|
||||||
|
|
||||||
@ -473,7 +527,55 @@ write(
|
|||||||
template<
|
template<
|
||||||
class SyncWriteStream,
|
class SyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields>
|
bool isRequest, class Body, class Fields>
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
std::size_t
|
std::size_t
|
||||||
|
#else
|
||||||
|
typename std::enable_if<
|
||||||
|
is_mutable_body_writer<Body>::value,
|
||||||
|
std::size_t>::type
|
||||||
|
#endif
|
||||||
|
write(
|
||||||
|
SyncWriteStream& stream,
|
||||||
|
message<isRequest, Body, Fields>& msg,
|
||||||
|
error_code& ec);
|
||||||
|
|
||||||
|
/** Write a complete message to a stream.
|
||||||
|
|
||||||
|
This function is used to write a complete message to a stream using
|
||||||
|
HTTP/1. The call will block until one of the following conditions is true:
|
||||||
|
|
||||||
|
@li The entire message is written.
|
||||||
|
|
||||||
|
@li An error occurs.
|
||||||
|
|
||||||
|
This operation is implemented in terms of one or more calls to the stream's
|
||||||
|
`write_some` function. The algorithm will use a temporary @ref serializer
|
||||||
|
with an empty chunk decorator to produce buffers.
|
||||||
|
|
||||||
|
@note This function only participates in overload resolution
|
||||||
|
if @ref is_mutable_body_writer for @b Body returns `false`.
|
||||||
|
|
||||||
|
@param stream The stream to which the data is to be written.
|
||||||
|
The type must support the @b SyncWriteStream concept.
|
||||||
|
|
||||||
|
@param msg The message to write.
|
||||||
|
|
||||||
|
@param ec Set to the error, if any occurred.
|
||||||
|
|
||||||
|
@return The number of bytes written to the stream.
|
||||||
|
|
||||||
|
@see @ref message
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
class SyncWriteStream,
|
||||||
|
bool isRequest, class Body, class Fields>
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
|
std::size_t
|
||||||
|
#else
|
||||||
|
typename std::enable_if<
|
||||||
|
! is_mutable_body_writer<Body>::value,
|
||||||
|
std::size_t>::type
|
||||||
|
#endif
|
||||||
write(
|
write(
|
||||||
SyncWriteStream& stream,
|
SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Fields> const& msg,
|
message<isRequest, Body, Fields> const& msg,
|
||||||
@ -495,6 +597,9 @@ write(
|
|||||||
until this operation completes. The algorithm will use a temporary
|
until this operation completes. The algorithm will use a temporary
|
||||||
@ref serializer with an empty chunk decorator to produce buffers.
|
@ref serializer with an empty chunk decorator to produce buffers.
|
||||||
|
|
||||||
|
@note This function only participates in overload resolution
|
||||||
|
if @ref is_mutable_body_writer for @b Body returns `true`.
|
||||||
|
|
||||||
@param stream The stream to which the data is to be written.
|
@param stream The stream to which the data is to be written.
|
||||||
The type must support the @b AsyncWriteStream concept.
|
The type must support the @b AsyncWriteStream concept.
|
||||||
|
|
||||||
@ -520,13 +625,78 @@ template<
|
|||||||
class AsyncWriteStream,
|
class AsyncWriteStream,
|
||||||
bool isRequest, class Body, class Fields,
|
bool isRequest, class Body, class Fields,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler, void(error_code, std::size_t))
|
WriteHandler, void(error_code, std::size_t))
|
||||||
|
#else
|
||||||
|
typename std::enable_if<
|
||||||
|
is_mutable_body_writer<Body>::value,
|
||||||
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
|
WriteHandler, void(error_code, std::size_t))>::type
|
||||||
|
#endif
|
||||||
async_write(
|
async_write(
|
||||||
AsyncWriteStream& stream,
|
AsyncWriteStream& stream,
|
||||||
message<isRequest, Body, Fields>& msg,
|
message<isRequest, Body, Fields>& msg,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
|
/** Write a complete message to a stream asynchronously.
|
||||||
|
|
||||||
|
This function is used to write a complete message to a stream asynchronously
|
||||||
|
using HTTP/1. The function call always returns immediately. The asynchronous
|
||||||
|
operation will continue until one of the following conditions is true:
|
||||||
|
|
||||||
|
@li The entire message is written.
|
||||||
|
|
||||||
|
@li An error occurs.
|
||||||
|
|
||||||
|
This operation is implemented in terms of zero or more calls to the stream's
|
||||||
|
`async_write_some` function, and is known as a <em>composed operation</em>.
|
||||||
|
The program must ensure that the stream performs no other writes
|
||||||
|
until this operation completes. The algorithm will use a temporary
|
||||||
|
@ref serializer with an empty chunk decorator to produce buffers.
|
||||||
|
|
||||||
|
@note This function only participates in overload resolution
|
||||||
|
if @ref is_mutable_body_writer for @b Body returns `false`.
|
||||||
|
|
||||||
|
@param stream The stream to which the data is to be written.
|
||||||
|
The type must support the @b AsyncWriteStream concept.
|
||||||
|
|
||||||
|
@param msg The message to write.
|
||||||
|
The object must remain valid at least until the
|
||||||
|
handler is called; ownership is not transferred.
|
||||||
|
|
||||||
|
@param handler Invoked when the operation completes.
|
||||||
|
The handler may be moved or copied as needed.
|
||||||
|
The equivalent function signature of the handler must be:
|
||||||
|
@code void handler(
|
||||||
|
error_code const& error, // result of operation
|
||||||
|
std::size_t bytes_transferred // the number of bytes written to the stream
|
||||||
|
); @endcode
|
||||||
|
Regardless of whether the asynchronous operation completes
|
||||||
|
immediately or not, the handler will not be invoked from within
|
||||||
|
this function. Invocation of the handler will be performed in a
|
||||||
|
manner equivalent to using `boost::asio::io_context::post`.
|
||||||
|
|
||||||
|
@see @ref message
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
class AsyncWriteStream,
|
||||||
|
bool isRequest, class Body, class Fields,
|
||||||
|
class WriteHandler>
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
|
WriteHandler, void(error_code, std::size_t))
|
||||||
|
#else
|
||||||
|
typename std::enable_if<
|
||||||
|
! is_mutable_body_writer<Body>::value,
|
||||||
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
|
WriteHandler, void(error_code, std::size_t))>::type
|
||||||
|
#endif
|
||||||
|
async_write(
|
||||||
|
AsyncWriteStream& stream,
|
||||||
|
message<isRequest, Body, Fields> const& msg,
|
||||||
|
WriteHandler&& handler);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Serialize an HTTP/1 header to a `std::ostream`.
|
/** Serialize an HTTP/1 header to a `std::ostream`.
|
||||||
|
@ -50,8 +50,9 @@ public:
|
|||||||
boost::asio::const_buffer;
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
writer(
|
||||||
writer(header<isRequest, Fields> const&, value_type const& b)
|
header<isRequest, Fields> const&,
|
||||||
|
value_type const& b)
|
||||||
: body_(b)
|
: body_(b)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -94,8 +95,9 @@ public:
|
|||||||
boost::asio::const_buffer;
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
writer(
|
||||||
writer(header<isRequest, Fields> const&, value_type const& b)
|
header<isRequest, Fields> const&,
|
||||||
|
value_type const& b)
|
||||||
: body_(b)
|
: body_(b)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -890,6 +892,107 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct const_body_writer
|
||||||
|
{
|
||||||
|
struct value_type{};
|
||||||
|
|
||||||
|
struct writer
|
||||||
|
{
|
||||||
|
using const_buffers_type =
|
||||||
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
|
template<bool isRequest, class Fields>
|
||||||
|
writer(
|
||||||
|
header<isRequest, Fields> const&,
|
||||||
|
value_type const&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init(error_code& ec)
|
||||||
|
{
|
||||||
|
ec.assign(0, ec.category());
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<std::pair<const_buffers_type, bool>>
|
||||||
|
get(error_code& ec)
|
||||||
|
{
|
||||||
|
ec.assign(0, ec.category());
|
||||||
|
return {{const_buffers_type{"", 0}, false}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mutable_body_writer
|
||||||
|
{
|
||||||
|
struct value_type{};
|
||||||
|
|
||||||
|
struct writer
|
||||||
|
{
|
||||||
|
using const_buffers_type =
|
||||||
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
|
template<bool isRequest, class Fields>
|
||||||
|
writer(
|
||||||
|
header<isRequest, Fields>&,
|
||||||
|
value_type&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init(error_code& ec)
|
||||||
|
{
|
||||||
|
ec.assign(0, ec.category());
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<std::pair<const_buffers_type, bool>>
|
||||||
|
get(error_code& ec)
|
||||||
|
{
|
||||||
|
ec.assign(0, ec.category());
|
||||||
|
return {{const_buffers_type{"", 0}, false}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
testBodyWriters()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
test::stream s{ioc_};
|
||||||
|
message<true, const_body_writer> m;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
write(s, m);
|
||||||
|
}
|
||||||
|
catch(std::exception const&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
test::stream s{ioc_};
|
||||||
|
message<true, const_body_writer> m;
|
||||||
|
write(s, m, ec);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test::stream s{ioc_};
|
||||||
|
message<true, mutable_body_writer> m;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
write(s, m);
|
||||||
|
}
|
||||||
|
catch(std::exception const&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
test::stream s{ioc_};
|
||||||
|
message<true, mutable_body_writer> m;
|
||||||
|
write(s, m, ec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
@ -912,6 +1015,7 @@ public:
|
|||||||
testWriteStream<test_body< true, true>>(yield);
|
testWriteStream<test_body< true, true>>(yield);
|
||||||
});
|
});
|
||||||
testAsioHandlerInvoke();
|
testAsioHandlerInvoke();
|
||||||
|
testBodyWriters();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user