mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
BodyReader, BodyWriter use two-phase init (API Change):
These types now perform error-based initialization in a separate init() functions instead of in the constructor. Actions Required: * Modify instances of user-defined BodyReader and BodyWriter types to perfrom two-phase initialization, as per the updated documented type requirements.
This commit is contained in:
@ -10,12 +10,17 @@ Version 76:
|
||||
API Changes:
|
||||
|
||||
* Rename to serializer::keep_alive
|
||||
* BodyReader, BodyWriter use two-phase init
|
||||
|
||||
Actions Required:
|
||||
|
||||
* Use serializer::keep_alive instead of serializer::close and
|
||||
take the logical NOT of the return value.
|
||||
|
||||
* Modify instances of user-defined BodyReader and BodyWriter
|
||||
types to perfrom two-phase initialization, as per the
|
||||
updated documented type requirements.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 75:
|
||||
|
@ -36,8 +36,14 @@ In this table:
|
||||
|
||||
* `R<T>` is the type `boost::optional<std::pair<T, bool>>`.
|
||||
|
||||
[table BodyReader requirements
|
||||
[[expression] [type] [semantics, pre/post-conditions]]
|
||||
[heading Associated Types]
|
||||
|
||||
* __Body__
|
||||
* [link beast.ref.beast__http__is_body_reader `is_body_reader`]
|
||||
|
||||
[heading BodyReader requirements]
|
||||
[table Valid Expressions
|
||||
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
|
||||
[
|
||||
[`X::const_buffers_type`]
|
||||
[]
|
||||
@ -46,22 +52,33 @@ In this table:
|
||||
This is the type of buffer returned by `X::get`.
|
||||
]
|
||||
][
|
||||
[`X(m,ec);`]
|
||||
[`X(m);`]
|
||||
[]
|
||||
[
|
||||
Constructible from `m`. The lifetime of `m` is guaranteed
|
||||
to end no earlier than after the `X` is destroyed.
|
||||
The reader shall not access the contents of `m` before the
|
||||
first call to `init`, permitting lazy construction of the
|
||||
message.
|
||||
|
||||
The constructor may optionally require that `m` is const, which
|
||||
has these consequences:
|
||||
|
||||
* If `X` requires that `m` is a const reference, then serializers
|
||||
constructed for messages with this body type will also require a
|
||||
`const` reference to a message, otherwise:
|
||||
const reference to a message, otherwise:
|
||||
|
||||
* If `X` requires that `m` is a non-const reference, then serializers
|
||||
constructed for messages with this body type will aso require
|
||||
a non-const reference to a message.
|
||||
|
||||
]
|
||||
][
|
||||
[`a.init(ec)`]
|
||||
[]
|
||||
[
|
||||
Called once to fully initialize the object before any calls to
|
||||
`get`. The message body becomes valid before entering this function,
|
||||
and remains valid until the reader is destroyed.
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
@ -69,9 +86,9 @@ In this table:
|
||||
[`a.get(ec)`]
|
||||
[`R<X::const_buffers_type>`]
|
||||
[
|
||||
Called repeatedly after `init` succeeds. This function returns
|
||||
`boost::none` if all buffers representing the body have been
|
||||
returned in previous calls or if it sets `ec` to indicate an
|
||||
Called one or more times after `init` succeeds. This function
|
||||
returns `boost::none` if all buffers representing the body have
|
||||
been returned in previous calls or if it sets `ec` to indicate an
|
||||
error. Otherwise, if there are buffers remaining the function
|
||||
should return a pair with the first element containing a non-zero
|
||||
length buffer sequence representing the next set of octets in
|
||||
@ -82,13 +99,6 @@ In this table:
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
][
|
||||
[`is_body_reader<B>`]
|
||||
[`std::true_type`]
|
||||
[
|
||||
An alias for `std::true_type` for `B`, otherwise an alias
|
||||
for `std::false_type`.
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
@ -96,4 +106,11 @@ In this table:
|
||||
|
||||
[concept_BodyReader]
|
||||
|
||||
[heading Models]
|
||||
|
||||
* [link beast.ref.beast__http__basic_dynamic_body.reader `basic_dynamic_body::reader`]
|
||||
* [link beast.ref.beast__http__basic_file_body__reader `basic_file_body::reader`]
|
||||
* [link beast.ref.beast__http__empty_body.reader `empty_body::reader`]
|
||||
* [link beast.ref.beast__http__string_body.reader `string_body::reader`]
|
||||
|
||||
[endsect]
|
||||
|
@ -38,20 +38,40 @@ In this table:
|
||||
|
||||
* `ec` is a value of type [link beast.ref.beast__error_code `error_code&`].
|
||||
|
||||
[heading Associated Types]
|
||||
|
||||
* __Body__
|
||||
* [link beast.ref.beast__http__is_body_writer `is_body_writer`]
|
||||
|
||||
[table Writer requirements
|
||||
[[expression] [type] [semantics, pre/post-conditions]]
|
||||
[
|
||||
[`X(m,n,ec);`]
|
||||
[`X(m);`]
|
||||
[]
|
||||
[
|
||||
Constructible from `m`. The lifetime of `m` is guaranteed
|
||||
to end no earlier than after the `X` is destroyed. The constructor
|
||||
will be called after a complete header is stored in `m`, and before
|
||||
parsing body octets for messages indicating that a body is present.
|
||||
Constructible from `m`. The lifetime of `m` is guaranteed to
|
||||
end no earlier than after the `X` is destroyed. The constructor
|
||||
will be called after a complete header is stored in `m`, and
|
||||
before parsing body octets for messages indicating that a body
|
||||
is present The writer shall not access the contents of `m` before
|
||||
the first call to `init`, permitting lazy construction of the
|
||||
message.
|
||||
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
][
|
||||
[`a.init(n, ec)`]
|
||||
[]
|
||||
[
|
||||
Called once to fully initialize the object before any calls to
|
||||
`put`. The message body is valid before entering this function,
|
||||
and remains valid until the writer is destroyed.
|
||||
The value of `n` will be set to the content length of the
|
||||
body if known, otherwise `n` will be equal to `boost::none`.
|
||||
Implementations of [*BodyWriter] may use this information to
|
||||
optimize allocation.
|
||||
|
||||
The function will ensure that `!ec` is `true` if there was
|
||||
no error or set to the appropriate error code if there was one.
|
||||
]
|
||||
@ -89,4 +109,11 @@ In this table:
|
||||
|
||||
[concept_BodyWriter]
|
||||
|
||||
[heading Models]
|
||||
|
||||
* [link beast.ref.beast__http__basic_dynamic_body.writer `basic_dynamic_body::writer`]
|
||||
* [link beast.ref.beast__http__basic_file_body__reader `basic_file_body::writer`]
|
||||
* [link beast.ref.beast__http__empty_body.writer `empty_body::writer`]
|
||||
* [link beast.ref.beast__http__string_body.writer `string_body::writer`]
|
||||
|
||||
[endsect]
|
||||
|
@ -68,9 +68,14 @@ struct const_body
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(beast::http::message<isRequest, const_body,
|
||||
Fields> const& msg, beast::error_code& ec)
|
||||
reader(beast::http::message<isRequest,
|
||||
const_body, Fields> const& msg)
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(beast::error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
@ -71,9 +71,14 @@ struct mutable_body
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(beast::http::message<isRequest, mutable_body,
|
||||
Fields> const& msg, beast::error_code& ec)
|
||||
reader(beast::http::message<isRequest,
|
||||
mutable_body, Fields> const& msg)
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(beast::error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
@ -99,15 +104,20 @@ struct mutable_body
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(beast::http::message<isRequest, mutable_body, Fields>& m,
|
||||
boost::optional<std::uint64_t> const& content_length,
|
||||
beast::error_code& ec)
|
||||
writer(beast::http::message<
|
||||
isRequest, mutable_body, Fields>& m)
|
||||
: body_(m.body)
|
||||
{
|
||||
if(content_length)
|
||||
}
|
||||
|
||||
void
|
||||
init(boost::optional<
|
||||
std::uint64_t> const& length, beast::error_code& ec)
|
||||
{
|
||||
if(length)
|
||||
{
|
||||
if(*content_length > (std::numeric_limits<
|
||||
std::size_t>::max)())
|
||||
if(*length > (std::numeric_limits<
|
||||
std::size_t>::max)())
|
||||
{
|
||||
ec = beast::http::error::buffer_overflow;
|
||||
return;
|
||||
@ -115,7 +125,7 @@ struct mutable_body
|
||||
try
|
||||
{
|
||||
body_.reserve(static_cast<
|
||||
std::size_t>(*content_length));
|
||||
std::size_t>(*length));
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
@ -129,7 +139,7 @@ struct mutable_body
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t
|
||||
put(ConstBufferSequence const& buffers,
|
||||
beast::error_code& ec)
|
||||
beast::error_code& ec)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::buffer_copy;
|
||||
|
@ -101,9 +101,14 @@ struct buffer_body
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest, buffer_body,
|
||||
Fields> const& msg, error_code& ec)
|
||||
reader(message<isRequest,
|
||||
buffer_body, Fields> const& msg)
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
@ -152,10 +157,13 @@ struct buffer_body
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest, buffer_body, Fields>& m,
|
||||
boost::optional<std::uint64_t> const&,
|
||||
error_code& ec)
|
||||
writer(message<isRequest, buffer_body, Fields>& m)
|
||||
: body_(m.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(boost::optional<std::uint64_t> const&, error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
@ -55,9 +55,14 @@ struct basic_dynamic_body
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest, basic_dynamic_body,
|
||||
Fields> const& m, error_code& ec)
|
||||
reader(message<isRequest,
|
||||
basic_dynamic_body, Fields> const& m)
|
||||
: body_(m.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
@ -82,10 +87,13 @@ struct basic_dynamic_body
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest, basic_dynamic_body, Fields>& msg,
|
||||
boost::optional<std::uint64_t> const&,
|
||||
error_code& ec)
|
||||
writer(message<isRequest, basic_dynamic_body, Fields>& msg)
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(boost::optional<std::uint64_t> const&, error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
@ -54,8 +54,13 @@ struct empty_body
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest, empty_body,
|
||||
Fields> const&, error_code& ec)
|
||||
reader(message<isRequest,
|
||||
empty_body, Fields> const&)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
@ -77,9 +82,12 @@ struct empty_body
|
||||
{
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest, empty_body, Fields>&,
|
||||
boost::optional<std::uint64_t> const&,
|
||||
error_code& ec)
|
||||
writer(message<isRequest, empty_body, Fields>&)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(boost::optional<std::uint64_t> const&, error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
@ -235,9 +235,17 @@ public:
|
||||
// always have the `file_body` as the body type.
|
||||
//
|
||||
template<bool isRequest, class Fields>
|
||||
reader(
|
||||
message<isRequest, basic_file_body, Fields> const& m,
|
||||
error_code& ec);
|
||||
reader(message<
|
||||
isRequest, basic_file_body, Fields> const& m);
|
||||
|
||||
// Initializer
|
||||
//
|
||||
// This is called before the body is serialized and
|
||||
// gives the reader a chance to do something that might
|
||||
// need to return an error code.
|
||||
//
|
||||
void
|
||||
init(error_code& ec);
|
||||
|
||||
// This function is called zero or more times to
|
||||
// retrieve buffers. A return value of `boost::none`
|
||||
@ -261,18 +269,29 @@ template<class File>
|
||||
template<bool isRequest, class Fields>
|
||||
basic_file_body<File>::
|
||||
reader::
|
||||
reader(
|
||||
message<isRequest, basic_file_body, Fields> const& m,
|
||||
error_code& ec)
|
||||
reader(message<isRequest, basic_file_body, Fields> const& m)
|
||||
: body_(m.body)
|
||||
{
|
||||
// The file must already be open
|
||||
BOOST_ASSERT(body_.file_.is_open());
|
||||
|
||||
// Get the size of the file
|
||||
remain_ = body_.file_.size(ec);
|
||||
if(ec)
|
||||
return;
|
||||
remain_ = body_.file_size_;
|
||||
}
|
||||
|
||||
// Initializer
|
||||
template<class File>
|
||||
void
|
||||
basic_file_body<File>::
|
||||
reader::
|
||||
init(error_code& ec)
|
||||
{
|
||||
// The error_code specification requires that we
|
||||
// either set the error to some value, or set it
|
||||
// to indicate no error.
|
||||
//
|
||||
// We don't do anything fancy so set "no error"
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
// This function is called repeatedly by the serializer to
|
||||
@ -353,9 +372,18 @@ public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(
|
||||
message<isRequest, basic_file_body, Fields>& m,
|
||||
boost::optional<std::uint64_t> const& content_length,
|
||||
error_code& ec);
|
||||
message<isRequest, basic_file_body, Fields>& m);
|
||||
|
||||
// Initializer
|
||||
//
|
||||
// This is called before the body is parsed and
|
||||
// gives the writer a chance to do something that might
|
||||
// need to return an error code. It informs us of
|
||||
// the payload size (`content_length`) which we can
|
||||
// optionally use for optimization.
|
||||
//
|
||||
void
|
||||
init(boost::optional<std::uint64_t> const&, error_code& ec);
|
||||
|
||||
// This function is called one or more times to store
|
||||
// buffer sequences corresponding to the incoming body.
|
||||
@ -387,11 +415,18 @@ template<class File>
|
||||
template<bool isRequest, class Fields>
|
||||
basic_file_body<File>::
|
||||
writer::
|
||||
writer(
|
||||
message<isRequest, basic_file_body, Fields>& m,
|
||||
writer(message<isRequest, basic_file_body, Fields>& m)
|
||||
: body_(m.body)
|
||||
{
|
||||
}
|
||||
|
||||
template<class File>
|
||||
void
|
||||
basic_file_body<File>::
|
||||
writer::
|
||||
init(
|
||||
boost::optional<std::uint64_t> const& content_length,
|
||||
error_code& ec)
|
||||
: body_(m.body)
|
||||
{
|
||||
// The file must already be open for writing
|
||||
BOOST_ASSERT(body_.file_.is_open());
|
||||
@ -401,7 +436,11 @@ writer(
|
||||
// to see if there is enough room to store the body.
|
||||
boost::ignore_unused(content_length);
|
||||
|
||||
// This is required by the error_code specification
|
||||
// The error_code specification requires that we
|
||||
// either set the error to some value, or set it
|
||||
// to indicate no error.
|
||||
//
|
||||
// We don't do anything fancy so set "no error"
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
|
@ -14,12 +14,20 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<bool isRequest, class Body, class Allocator>
|
||||
parser<isRequest, Body, Allocator>::
|
||||
parser()
|
||||
: wr_(m_)
|
||||
{
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Allocator>
|
||||
template<class Arg1, class... ArgN, class>
|
||||
parser<isRequest, Body, Allocator>::
|
||||
parser(Arg1&& arg1, ArgN&&... argn)
|
||||
: m_(std::forward<Arg1>(arg1),
|
||||
std::forward<ArgN>(argn)...)
|
||||
, wr_(m_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -30,8 +38,9 @@ parser(parser<isRequest, OtherBody, Allocator>&& p,
|
||||
Args&&... args)
|
||||
: base_type(std::move(p))
|
||||
, m_(p.release(), std::forward<Args>(args)...)
|
||||
, wr_(m_)
|
||||
{
|
||||
if(p.wr_)
|
||||
if(wr_inited_)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
||||
"moved-from parser has a body"});
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ template<bool isRequest, class Body,
|
||||
serializer<isRequest, Body, Fields, ChunkDecorator>::
|
||||
serializer(value_type& m)
|
||||
: m_(m)
|
||||
, rd_(m_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -67,6 +68,7 @@ template<bool isRequest, class Body,
|
||||
serializer<isRequest, Body, Fields, ChunkDecorator>::
|
||||
serializer(value_type& m, ChunkDecorator const& d)
|
||||
: m_(m)
|
||||
, rd_(m_)
|
||||
, d_(d)
|
||||
{
|
||||
}
|
||||
@ -96,12 +98,12 @@ next(error_code& ec, Visit&& visit)
|
||||
|
||||
case do_init:
|
||||
{
|
||||
if(split_)
|
||||
goto go_header_only;
|
||||
rd_.emplace(m_, ec);
|
||||
rd_.init(ec);
|
||||
if(ec)
|
||||
return;
|
||||
auto result = rd_->get(ec);
|
||||
if(split_)
|
||||
goto go_header_only;
|
||||
auto result = rd_.get(ec);
|
||||
if(ec == error::need_more)
|
||||
goto go_header_only;
|
||||
if(ec)
|
||||
@ -129,18 +131,12 @@ next(error_code& ec, Visit&& visit)
|
||||
break;
|
||||
|
||||
case do_body:
|
||||
if(! rd_)
|
||||
{
|
||||
rd_.emplace(m_, ec);
|
||||
if(ec)
|
||||
return;
|
||||
}
|
||||
s_ = do_body + 1;
|
||||
BEAST_FALLTHROUGH;
|
||||
|
||||
case do_body + 1:
|
||||
{
|
||||
auto result = rd_->get(ec);
|
||||
auto result = rd_.get(ec);
|
||||
if(ec)
|
||||
return;
|
||||
if(! result)
|
||||
@ -161,12 +157,12 @@ next(error_code& ec, Visit&& visit)
|
||||
s_ = do_init_c;
|
||||
case do_init_c:
|
||||
{
|
||||
if(split_)
|
||||
goto go_header_only_c;
|
||||
rd_.emplace(m_, ec);
|
||||
rd_.init(ec);
|
||||
if(ec)
|
||||
return;
|
||||
auto result = rd_->get(ec);
|
||||
if(split_)
|
||||
goto go_header_only_c;
|
||||
auto result = rd_.get(ec);
|
||||
if(ec == error::need_more)
|
||||
goto go_header_only_c;
|
||||
if(ec)
|
||||
@ -237,18 +233,12 @@ next(error_code& ec, Visit&& visit)
|
||||
break;
|
||||
|
||||
case do_body_c:
|
||||
if(! rd_)
|
||||
{
|
||||
rd_.emplace(m_, ec);
|
||||
if(ec)
|
||||
return;
|
||||
}
|
||||
s_ = do_body_c + 1;
|
||||
BEAST_FALLTHROUGH;
|
||||
|
||||
case do_body_c + 1:
|
||||
{
|
||||
auto result = rd_->get(ec);
|
||||
auto result = rd_.get(ec);
|
||||
if(ec)
|
||||
return;
|
||||
if(! result)
|
||||
|
@ -60,21 +60,17 @@ class parser
|
||||
parser<isRequest, Body, Allocator>>;
|
||||
|
||||
message<isRequest, Body, basic_fields<Allocator>> m_;
|
||||
boost::optional<typename Body::writer> wr_;
|
||||
typename Body::writer wr_;
|
||||
std::function<void(parser&, error_code&)> cb_;
|
||||
bool wr_inited_ = false;
|
||||
|
||||
public:
|
||||
/// The type of message returned by the parser
|
||||
using value_type =
|
||||
message<isRequest, Body, basic_fields<Allocator>>;
|
||||
|
||||
/// Constructor (default)
|
||||
parser()
|
||||
{
|
||||
// avoid `parser()=default` otherwise value-init
|
||||
// for members can happen (i.e. a big memset on
|
||||
// static_buffer_n).
|
||||
}
|
||||
/// Constructor
|
||||
parser();
|
||||
|
||||
/// Copy constructor (disallowed)
|
||||
parser(parser const&) = delete;
|
||||
@ -285,13 +281,14 @@ private:
|
||||
std::uint64_t> const& content_length,
|
||||
error_code& ec)
|
||||
{
|
||||
wr_.emplace(m_, content_length, ec);
|
||||
wr_.init(content_length, ec);
|
||||
wr_inited_ = true;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
on_data(string_view s, error_code& ec)
|
||||
{
|
||||
return wr_->put(boost::asio::buffer(
|
||||
return wr_.put(boost::asio::buffer(
|
||||
s.data(), s.size()), ec);
|
||||
}
|
||||
|
||||
@ -305,10 +302,7 @@ private:
|
||||
void
|
||||
on_complete(error_code& ec)
|
||||
{
|
||||
if(wr_)
|
||||
wr_->finish(ec);
|
||||
else
|
||||
ec.assign(0, ec.category());
|
||||
wr_.finish(ec);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -134,7 +134,7 @@ public:
|
||||
static_assert(is_body_reader<Body>::value,
|
||||
"BodyReader requirements not met");
|
||||
|
||||
/** The type of the message referenced by this object.
|
||||
/** The type of message this serializer uses
|
||||
|
||||
This may be const or non-const depending on the
|
||||
implementation of the corresponding @b BodyReader.
|
||||
@ -145,11 +145,9 @@ public:
|
||||
using value_type =
|
||||
typename std::conditional<
|
||||
std::is_constructible<typename Body::reader,
|
||||
message<isRequest, Body, Fields>&,
|
||||
error_code&>::value &&
|
||||
message<isRequest, Body, Fields>&>::value &&
|
||||
! std::is_constructible<typename Body::reader,
|
||||
message<isRequest, Body, Fields> const&,
|
||||
error_code&>::value,
|
||||
message<isRequest, Body, Fields> const&>::value,
|
||||
message<isRequest, Body, Fields>,
|
||||
message<isRequest, Body, Fields> const>::type;
|
||||
#endif
|
||||
@ -248,8 +246,8 @@ private:
|
||||
using pcb8_t = buffer_prefix_view<cb8_t const&>;
|
||||
|
||||
value_type& m_;
|
||||
reader rd_;
|
||||
boost::optional<typename Fields::reader> frd_;
|
||||
boost::optional<reader> rd_;
|
||||
boost::variant<boost::blank,
|
||||
cb1_t, cb2_t, cb3_t, cb4_t, cb5_t
|
||||
#ifndef BEAST_NO_BIG_VARIANTS
|
||||
|
@ -52,9 +52,14 @@ struct string_body
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest, string_body,
|
||||
Fields> const& msg, error_code& ec)
|
||||
reader(message<isRequest,
|
||||
string_body, Fields> const& msg)
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
@ -80,23 +85,27 @@ struct string_body
|
||||
public:
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest, string_body, Fields>& m,
|
||||
boost::optional<std::uint64_t> content_length,
|
||||
error_code& ec)
|
||||
writer(message<isRequest, string_body, Fields>& m)
|
||||
: body_(m.body)
|
||||
{
|
||||
if(content_length)
|
||||
}
|
||||
|
||||
void
|
||||
init(boost::optional<
|
||||
std::uint64_t> const& length, error_code& ec)
|
||||
{
|
||||
if(length)
|
||||
{
|
||||
if(*content_length > (std::numeric_limits<
|
||||
std::size_t>::max)())
|
||||
if(*length > (
|
||||
std::numeric_limits<std::size_t>::max)())
|
||||
{
|
||||
ec = error::buffer_overflow;
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
body_.reserve(static_cast<
|
||||
std::size_t>(*content_length));
|
||||
body_.reserve(
|
||||
static_cast<std::size_t>(*length));
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
|
@ -53,9 +53,14 @@ struct string_view_body
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest, string_view_body,
|
||||
Fields> const& m, error_code& ec)
|
||||
reader(message<isRequest,
|
||||
string_view_body, Fields> const& m)
|
||||
: body_(m.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ struct is_body_reader<T, beast::detail::void_t<
|
||||
typename T::reader,
|
||||
typename T::reader::const_buffers_type,
|
||||
decltype(
|
||||
std::declval<typename T::reader&>().init(std::declval<error_code&>()),
|
||||
std::declval<boost::optional<std::pair<
|
||||
typename T::reader::const_buffers_type, bool>>&>() =
|
||||
std::declval<typename T::reader>().get(std::declval<error_code&>()),
|
||||
@ -87,11 +88,9 @@ struct is_body_reader<T, beast::detail::void_t<
|
||||
is_const_buffer_sequence<
|
||||
typename T::reader::const_buffers_type>::value &&
|
||||
std::is_constructible<typename T::reader,
|
||||
message<true, T, detail::fields_model>&,
|
||||
error_code&>::value &&
|
||||
message<true, T, detail::fields_model>&>::value &&
|
||||
std::is_constructible<typename T::reader,
|
||||
message<false, T, detail::fields_model>&,
|
||||
error_code&>::value
|
||||
message<false, T, detail::fields_model>&>::value
|
||||
> {};
|
||||
#endif
|
||||
|
||||
@ -124,6 +123,9 @@ struct is_body_writer : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_body_writer<T, beast::detail::void_t<decltype(
|
||||
std::declval<typename T::writer&>().init(
|
||||
boost::optional<std::uint64_t>(),
|
||||
std::declval<error_code&>()),
|
||||
std::declval<std::size_t&>() =
|
||||
std::declval<typename T::writer&>().put(
|
||||
std::declval<boost::asio::const_buffers_1>(),
|
||||
@ -132,10 +134,10 @@ struct is_body_writer<T, beast::detail::void_t<decltype(
|
||||
std::declval<error_code&>()),
|
||||
(void)0)>> : std::integral_constant<bool,
|
||||
std::is_constructible<typename T::writer,
|
||||
message<true, T, detail::fields_model>&,
|
||||
boost::optional<std::uint64_t>,
|
||||
error_code&
|
||||
>::value>
|
||||
message<true, T, detail::fields_model>&>::value &&
|
||||
std::is_constructible<typename T::writer,
|
||||
message<false, T, detail::fields_model>&>::value
|
||||
>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
@ -58,10 +58,24 @@ public:
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
explicit
|
||||
BodyReader(message<isRequest, Body, Headers> const& msg,
|
||||
error_code &ec);
|
||||
BodyReader(message<isRequest, Body, Fields> const& msg);
|
||||
|
||||
/** Initialize the reader
|
||||
|
||||
This is called after construction and before the first
|
||||
call to `get`. The message is valid and complete upon
|
||||
entry.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
/** Returns the next buffer in the body.
|
||||
|
||||
@ -85,7 +99,7 @@ public:
|
||||
get(error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
ec.assign(0, ec.category());
|
||||
|
||||
return boost::none; // for exposition only
|
||||
}
|
||||
@ -109,14 +123,25 @@ struct BodyWriter
|
||||
*/
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
explicit
|
||||
BodyWriter(message<isRequest, Body, Fields>& msg,
|
||||
boost::optional<std::uint64_t> content_length,
|
||||
error_code& ec)
|
||||
BodyWriter(message<isRequest, Body, Fields>& msg);
|
||||
|
||||
/** Initialize the writer
|
||||
|
||||
This is called after construction and before the first
|
||||
call to `put`. The message is valid and complete upon
|
||||
entry.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
init(
|
||||
boost::optional<std::uint64_t> const& content_length,
|
||||
error_code& ec)
|
||||
{
|
||||
boost::ignore_unused(msg, content_length);
|
||||
boost::ignore_unused(content_length);
|
||||
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
/** Store buffers.
|
||||
|
@ -27,8 +27,10 @@ public:
|
||||
boost::asio::const_buffers_1;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
reader(message<isRequest, const_body, Fields> const&,
|
||||
error_code&);
|
||||
reader(message<isRequest, const_body, Fields> const&);
|
||||
|
||||
void
|
||||
init(error_code& ec);
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code&);
|
||||
@ -45,8 +47,10 @@ public:
|
||||
boost::asio::const_buffers_1;
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
reader(message<isRequest, mutable_body, Fields>&,
|
||||
error_code&);
|
||||
reader(message<isRequest, mutable_body, Fields>&);
|
||||
|
||||
void
|
||||
init(error_code& ec);
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code&);
|
||||
@ -55,6 +59,7 @@ public:
|
||||
|
||||
BOOST_STATIC_ASSERT(std::is_const< serializer<
|
||||
true, const_body>::value_type>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(! std::is_const<serializer<
|
||||
true, mutable_body>::value_type>::value);
|
||||
|
||||
|
@ -47,13 +47,18 @@ public:
|
||||
|
||||
template<bool isRequest, class Allocator>
|
||||
explicit
|
||||
reader(message<isRequest, unsized_body,
|
||||
Allocator> const& msg, error_code &ec)
|
||||
reader(message<isRequest,
|
||||
unsized_body, Allocator> const& msg)
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
|
||||
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
@ -87,9 +92,14 @@ public:
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest, test_body,
|
||||
Fields> const& msg, error_code& ec)
|
||||
reader(message<isRequest,
|
||||
test_body, Fields> const& msg)
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
@ -219,9 +229,14 @@ public:
|
||||
|
||||
template<bool isRequest, class Allocator>
|
||||
explicit
|
||||
reader(message<isRequest, fail_body,
|
||||
Allocator> const& msg, error_code& ec)
|
||||
reader(message<isRequest,
|
||||
fail_body, Allocator> const& msg)
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
body_.fc_.fail(ec);
|
||||
}
|
||||
|
Reference in New Issue
Block a user