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