forked from boostorg/beast
New BodyReader and BodyWriter constructors (API Change):
fix #884 * BodyReader and BodyWriter constructors now require the header and body elements to be passed as distinct header and value_type objects. This enables the composition of body types, for example: http::response<compressed_body<http::string_body>> res; * The previous single-argument constructors are deprecated and will be removed in a subsequent version. Actions Required: * Change user-defined instances of BodyReader or BodyWriter constructor signatures to the two-argument form. OR * Define the macro BOOST_BEAST_ALLOW_DEPRECATED in the project (which will accept both the new and the deprecated signatures).
This commit is contained in:
committed by
Vinnie Falco
parent
d796319476
commit
b76ab4450a
@@ -41,27 +41,25 @@ In this table:
|
|||||||
`std::is_same<R, B::reader>::value == true`.
|
`std::is_same<R, B::reader>::value == true`.
|
||||||
* `a` denotes a value of type `R`.
|
* `a` denotes a value of type `R`.
|
||||||
* `b` is an object whose type meets the requirements of __ConstBufferSequence__
|
* `b` is an object whose type meets the requirements of __ConstBufferSequence__
|
||||||
* `m` denotes a value of type `message&` where
|
* `h` denotes a value of type `header<isRequest, Fields>&`.
|
||||||
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
|
* `v` denotes a value of type `Body::value_type&`.
|
||||||
* `n` is a value of type `boost::optional<std::uint64_t>`.
|
* `n` is a value of type `boost::optional<std::uint64_t>`.
|
||||||
* `ec` is a value of type [link beast.ref.boost__beast__error_code `error_code&`].
|
* `ec` is a value of type [link beast.ref.boost__beast__error_code `error_code&`].
|
||||||
|
|
||||||
[table Valid expressions
|
[table Valid expressions
|
||||||
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
|
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
|
||||||
[
|
[
|
||||||
[`R{m};`]
|
[`R{h,v};`]
|
||||||
[]
|
[]
|
||||||
[
|
[
|
||||||
Constructible from `m`. The lifetime of `m` is guaranteed to
|
Constructible from `h` and `v`. The lifetime of `h` and `v`
|
||||||
end no earlier than after the `R` is destroyed. The constructor
|
is guaranteed to end no earlier than after the `R` is destroyed.
|
||||||
will be called after a complete header is stored in `m`, and
|
The constructor will be called after a complete header is stored
|
||||||
before parsing body octets for messages indicating that a body
|
in `h`, and before parsing body octets for messages indicating
|
||||||
is present The reader shall not access the contents of `m` before
|
that a body is present.
|
||||||
|
The reader shall not access the contents of `h` or `v` before
|
||||||
the first call to `init`, permitting lazy construction of the
|
the first call to `init`, permitting lazy construction of the
|
||||||
message.
|
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)`]
|
[`a.init(n, ec)`]
|
||||||
|
@@ -42,8 +42,8 @@ In this table:
|
|||||||
* `B` denotes a __Body__ where
|
* `B` denotes a __Body__ where
|
||||||
`std::is_same<W, B::writer>::value == true`.
|
`std::is_same<W, B::writer>::value == true`.
|
||||||
* `a` denotes a value of type `W`.
|
* `a` denotes a value of type `W`.
|
||||||
* `m` denotes a possibly const value of type `message&` where
|
* `h` denotes a const value of type `header<isRequest, Fields> const&`.
|
||||||
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
|
* `v` denotes a possibly const value of type `Body::value_type&`.
|
||||||
* `ec` is a value of type [link beast.ref.boost__beast__error_code `error_code&`].
|
* `ec` is a value of type [link beast.ref.boost__beast__error_code `error_code&`].
|
||||||
* `W<T>` is the type `boost::optional<std::pair<T, bool>>`.
|
* `W<T>` is the type `boost::optional<std::pair<T, bool>>`.
|
||||||
|
|
||||||
@@ -57,23 +57,23 @@ In this table:
|
|||||||
This is the type of buffer returned by `W::get`.
|
This is the type of buffer returned by `W::get`.
|
||||||
]
|
]
|
||||||
][
|
][
|
||||||
[`W{m};`]
|
[`W{h,v};`]
|
||||||
[]
|
[]
|
||||||
[
|
[
|
||||||
Constructible from `m`. The lifetime of `m` is guaranteed
|
Constructible from `h` and `v`. The lifetime of `h` and `v`
|
||||||
to end no earlier than after the `W` is destroyed.
|
is guaranteed to end no earlier than after the `W` is destroyed.
|
||||||
The writer shall not access the contents of `m` before the
|
The writer shall not access the contents of `h` or `v` before
|
||||||
first call to `init`, permitting lazy construction of the
|
the first call to `init`, permitting lazy construction of the
|
||||||
message.
|
message.
|
||||||
|
|
||||||
The constructor may optionally require that `m` is const, which
|
The constructor may optionally require that `v` is const, which
|
||||||
has these consequences:
|
has these consequences:
|
||||||
|
|
||||||
* If `W` requires that `m` is a const reference, then serializers
|
* If `W` requires that `v` 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 `W` requires that `m` is a non-const reference, then serializers
|
* If `W` requires that `v` 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.
|
||||||
]
|
]
|
||||||
|
@@ -70,9 +70,8 @@ struct basic_dynamic_body
|
|||||||
public:
|
public:
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest,
|
reader(header<isRequest, Fields>&, value_type& b)
|
||||||
basic_dynamic_body, Fields>& msg)
|
: body_(b)
|
||||||
: body_(msg.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,9 +139,8 @@ struct basic_dynamic_body
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields> const&, value_type const& b)
|
||||||
basic_dynamic_body, Fields> const& m)
|
: body_(b)
|
||||||
: body_(m.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -239,8 +239,8 @@ public:
|
|||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
//
|
//
|
||||||
// `m` holds the message we are serializing, which will
|
// `h` holds the headers of the message we are
|
||||||
// always have the `basic_file_body` as the body type.
|
// serializing, while `b` holds the body.
|
||||||
//
|
//
|
||||||
// Note that the message is passed by non-const reference.
|
// Note that the message is passed by non-const reference.
|
||||||
// This is intentional, because reading from the file
|
// This is intentional, because reading from the file
|
||||||
@@ -262,8 +262,7 @@ public:
|
|||||||
// a time.
|
// a time.
|
||||||
//
|
//
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
writer(message<
|
writer(header<isRequest, Fields>& h, value_type& b);
|
||||||
isRequest, basic_file_body, Fields>& m);
|
|
||||||
|
|
||||||
// Initializer
|
// Initializer
|
||||||
//
|
//
|
||||||
@@ -296,9 +295,11 @@ template<class File>
|
|||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
basic_file_body<File>::
|
basic_file_body<File>::
|
||||||
writer::
|
writer::
|
||||||
writer(message<isRequest, basic_file_body, Fields>& m)
|
writer(header<isRequest, Fields>& h, value_type& b)
|
||||||
: body_(m.body())
|
: body_(b)
|
||||||
{
|
{
|
||||||
|
boost::ignore_unused(h);
|
||||||
|
|
||||||
// The file must already be open
|
// The file must already be open
|
||||||
BOOST_ASSERT(body_.file_.is_open());
|
BOOST_ASSERT(body_.file_.is_open());
|
||||||
|
|
||||||
@@ -398,13 +399,12 @@ public:
|
|||||||
//
|
//
|
||||||
// This is called after the header is parsed and
|
// This is called after the header is parsed and
|
||||||
// indicates that a non-zero sized body may be present.
|
// indicates that a non-zero sized body may be present.
|
||||||
// `m` holds the message we are receiving, which will
|
// `h` holds the received message headers.
|
||||||
// always have the `basic_file_body` as the body type.
|
// `b` is an instance of `basic_file_body`.
|
||||||
//
|
//
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(
|
reader(header<isRequest, Fields>&h, value_type& b);
|
||||||
message<isRequest, basic_file_body, Fields>& m);
|
|
||||||
|
|
||||||
// Initializer
|
// Initializer
|
||||||
//
|
//
|
||||||
@@ -447,9 +447,10 @@ template<class File>
|
|||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
basic_file_body<File>::
|
basic_file_body<File>::
|
||||||
reader::
|
reader::
|
||||||
reader(message<isRequest, basic_file_body, Fields>& m)
|
reader(header<isRequest, Fields>& h, value_type& body)
|
||||||
: body_(m.body())
|
: body_(body)
|
||||||
{
|
{
|
||||||
|
boost::ignore_unused(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class File>
|
template<class File>
|
||||||
|
@@ -105,8 +105,8 @@ struct buffer_body
|
|||||||
public:
|
public:
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest, buffer_body, Fields>& m)
|
reader(header<isRequest, Fields>&, value_type& b)
|
||||||
: body_(m.body())
|
: body_(b)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,9 +167,8 @@ struct buffer_body
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields> const&, value_type const& b)
|
||||||
buffer_body, Fields> const& msg)
|
: body_(b)
|
||||||
: body_(msg.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -194,6 +194,22 @@ struct is_fields_helper : T
|
|||||||
t10::value && t11::value && t12::value>;
|
t10::value && t11::value && t12::value>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using has_deprecated_body_writer =
|
||||||
|
std::integral_constant<bool,
|
||||||
|
std::is_constructible<typename T::writer,
|
||||||
|
message<true, T, detail::fields_model>&>::value &&
|
||||||
|
std::is_constructible<typename T::writer,
|
||||||
|
message<false, T, detail::fields_model>&>::value>;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using has_deprecated_body_reader =
|
||||||
|
std::integral_constant<bool,
|
||||||
|
std::is_constructible<typename T::reader,
|
||||||
|
message<true, T, detail::fields_model>&>::value &&
|
||||||
|
std::is_constructible<typename T::reader,
|
||||||
|
message<false, T, detail::fields_model>&>::value>;
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
@@ -63,7 +63,7 @@ struct empty_body
|
|||||||
{
|
{
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest, empty_body, Fields>&)
|
reader(header<isRequest, Fields>&, value_type&)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +104,7 @@ struct empty_body
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields> const&, value_type const&)
|
||||||
empty_body, Fields> const&)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -123,9 +123,8 @@ struct basic_file_body<file_win32>
|
|||||||
boost::asio::const_buffer;
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields>&, value_type& b)
|
||||||
basic_file_body<file_win32>, Fields>& m)
|
: body_(b)
|
||||||
: body_(m.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,8 +166,8 @@ struct basic_file_body<file_win32>
|
|||||||
public:
|
public:
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest, basic_file_body, Fields>& m)
|
reader(header<isRequest, Fields>&, value_type& b)
|
||||||
: body_(m.body())
|
: body_(b)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,26 +20,87 @@ namespace http {
|
|||||||
template<bool isRequest, class Body, class Allocator>
|
template<bool isRequest, class Body, class Allocator>
|
||||||
parser<isRequest, Body, Allocator>::
|
parser<isRequest, Body, Allocator>::
|
||||||
parser()
|
parser()
|
||||||
|
: parser{detail::has_deprecated_body_reader<Body>{}}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Allocator>
|
||||||
|
parser<isRequest, Body, Allocator>::
|
||||||
|
parser(std::true_type)
|
||||||
: rd_(m_)
|
: rd_(m_)
|
||||||
{
|
{
|
||||||
|
#ifndef BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
// Deprecated BodyReader Concept (v1.66)
|
||||||
|
static_assert(sizeof(Body) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Allocator>
|
||||||
|
parser<isRequest, Body, Allocator>::
|
||||||
|
parser(std::false_type)
|
||||||
|
: rd_(m_.base(), m_.body())
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
: parser(std::forward<Arg1>(arg1),
|
||||||
|
detail::has_deprecated_body_reader<Body>{},
|
||||||
|
std::forward<ArgN>(argn)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// VFALCO arg1 comes before `true_type` to make
|
||||||
|
// the signature unambiguous.
|
||||||
|
template<bool isRequest, class Body, class Allocator>
|
||||||
|
template<class Arg1, class... ArgN, class>
|
||||||
|
parser<isRequest, Body, Allocator>::
|
||||||
|
parser(Arg1&& arg1, std::true_type, ArgN&&... argn)
|
||||||
: m_(std::forward<Arg1>(arg1),
|
: m_(std::forward<Arg1>(arg1),
|
||||||
std::forward<ArgN>(argn)...)
|
std::forward<ArgN>(argn)...)
|
||||||
, rd_(m_)
|
, rd_(m_)
|
||||||
{
|
{
|
||||||
m_.clear();
|
m_.clear();
|
||||||
|
#ifndef BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
/* Deprecated BodyWriter Concept (v1.66) */
|
||||||
|
static_assert(sizeof(Body) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif // BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
}
|
||||||
|
|
||||||
|
// VFALCO arg1 comes before `false_type` to make
|
||||||
|
// the signature unambiguous.
|
||||||
|
template<bool isRequest, class Body, class Allocator>
|
||||||
|
template<class Arg1, class... ArgN, class>
|
||||||
|
parser<isRequest, Body, Allocator>::
|
||||||
|
parser(Arg1&& arg1, std::false_type, ArgN&&... argn)
|
||||||
|
: m_(std::forward<Arg1>(arg1),
|
||||||
|
std::forward<ArgN>(argn)...)
|
||||||
|
, rd_(m_.base(), m_.body())
|
||||||
|
{
|
||||||
|
m_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Allocator>
|
template<bool isRequest, class Body, class Allocator>
|
||||||
template<class OtherBody, class... Args, class>
|
template<class OtherBody, class... Args, class>
|
||||||
parser<isRequest, Body, Allocator>::
|
parser<isRequest, Body, Allocator>::
|
||||||
parser(parser<isRequest, OtherBody, Allocator>&& other,
|
parser(
|
||||||
Args&&... args)
|
parser<isRequest, OtherBody, Allocator>&& other,
|
||||||
|
Args&&... args)
|
||||||
|
: parser(detail::has_deprecated_body_reader<Body>{},
|
||||||
|
std::move(other), std::forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Allocator>
|
||||||
|
template<class OtherBody, class... Args, class>
|
||||||
|
parser<isRequest, Body, Allocator>::
|
||||||
|
parser(std::true_type,
|
||||||
|
parser<isRequest, OtherBody, Allocator>&& other,
|
||||||
|
Args&&... args)
|
||||||
: base_type(std::move(other))
|
: base_type(std::move(other))
|
||||||
, m_(other.release(), std::forward<Args>(args)...)
|
, m_(other.release(), std::forward<Args>(args)...)
|
||||||
, rd_(m_)
|
, rd_(m_)
|
||||||
@@ -47,6 +108,25 @@ parser(parser<isRequest, OtherBody, Allocator>&& other,
|
|||||||
if(other.rd_inited_)
|
if(other.rd_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"});
|
||||||
|
#ifndef BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
// Deprecated BodyReader Concept (v1.66)
|
||||||
|
static_assert(sizeof(Body) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Allocator>
|
||||||
|
template<class OtherBody, class... Args, class>
|
||||||
|
parser<isRequest, Body, Allocator>::
|
||||||
|
parser(std::false_type, parser<isRequest, OtherBody, Allocator>&& other,
|
||||||
|
Args&&... args)
|
||||||
|
: base_type(std::move(other))
|
||||||
|
, m_(other.release(), std::forward<Args>(args)...)
|
||||||
|
, rd_(m_.base(), m_.body())
|
||||||
|
{
|
||||||
|
if(other.rd_inited_)
|
||||||
|
BOOST_THROW_EXCEPTION(std::invalid_argument{
|
||||||
|
"moved-from parser has a body"});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
|
@@ -57,10 +57,32 @@ do_visit(error_code& ec, Visit& visit)
|
|||||||
template<
|
template<
|
||||||
bool isRequest, class Body, class Fields>
|
bool isRequest, class Body, class Fields>
|
||||||
serializer<isRequest, Body, Fields>::
|
serializer<isRequest, Body, Fields>::
|
||||||
serializer(value_type& m)
|
serializer(value_type& m, std::true_type)
|
||||||
: m_(m)
|
: m_(m)
|
||||||
, wr_(m_)
|
, wr_(m_)
|
||||||
{
|
{
|
||||||
|
#ifndef BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
|
// Deprecated BodyWriter Concept (v1.66)
|
||||||
|
static_assert(sizeof(Body) == 0,
|
||||||
|
BOOST_BEAST_DEPRECATION_STRING);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
bool isRequest, class Body, class Fields>
|
||||||
|
serializer<isRequest, Body, Fields>::
|
||||||
|
serializer(value_type& m, std::false_type)
|
||||||
|
: m_(m)
|
||||||
|
, wr_(m_.base(), m_.body())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
bool isRequest, class Body, class Fields>
|
||||||
|
serializer<isRequest, Body, Fields>::
|
||||||
|
serializer(value_type& m)
|
||||||
|
: serializer(m, detail::has_deprecated_body_writer<Body>{})
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
|
@@ -303,6 +303,39 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class basic_parser<isRequest, parser>;
|
friend class basic_parser<isRequest, parser>;
|
||||||
|
|
||||||
|
parser(std::true_type);
|
||||||
|
parser(std::false_type);
|
||||||
|
|
||||||
|
template<class OtherBody, class... Args,
|
||||||
|
class = typename std::enable_if<
|
||||||
|
! std::is_same<Body, OtherBody>::value>::type>
|
||||||
|
parser(
|
||||||
|
std::true_type,
|
||||||
|
parser<isRequest, OtherBody, Allocator>&& parser,
|
||||||
|
Args&&... args);
|
||||||
|
|
||||||
|
template<class OtherBody, class... Args,
|
||||||
|
class = typename std::enable_if<
|
||||||
|
! std::is_same<Body, OtherBody>::value>::type>
|
||||||
|
parser(
|
||||||
|
std::false_type,
|
||||||
|
parser<isRequest, OtherBody, Allocator>&& parser,
|
||||||
|
Args&&... args);
|
||||||
|
|
||||||
|
template<class Arg1, class... ArgN,
|
||||||
|
class = typename std::enable_if<
|
||||||
|
! detail::is_parser<typename
|
||||||
|
std::decay<Arg1>::type>::value>::type>
|
||||||
|
explicit
|
||||||
|
parser(Arg1&& arg1, std::true_type, ArgN&&... argn);
|
||||||
|
|
||||||
|
template<class Arg1, class... ArgN,
|
||||||
|
class = typename std::enable_if<
|
||||||
|
! detail::is_parser<typename
|
||||||
|
std::decay<Arg1>::type>::value>::type>
|
||||||
|
explicit
|
||||||
|
parser(Arg1&& arg1, std::false_type, ArgN&&... argn);
|
||||||
|
|
||||||
void
|
void
|
||||||
on_request_impl(
|
on_request_impl(
|
||||||
verb method,
|
verb method,
|
||||||
|
@@ -71,14 +71,20 @@ public:
|
|||||||
#if BOOST_BEAST_DOXYGEN
|
#if BOOST_BEAST_DOXYGEN
|
||||||
using value_type = implementation_defined;
|
using value_type = implementation_defined;
|
||||||
#else
|
#else
|
||||||
using value_type =
|
using value_type = typename std::conditional<
|
||||||
typename std::conditional<
|
(std::is_constructible<typename Body::writer,
|
||||||
std::is_constructible<typename Body::writer,
|
header<isRequest, Fields>&,
|
||||||
message<isRequest, Body, Fields>&>::value &&
|
typename Body::value_type&>::value &&
|
||||||
! std::is_constructible<typename Body::writer,
|
! std::is_constructible<typename Body::writer,
|
||||||
message<isRequest, Body, Fields> const&>::value,
|
header<isRequest, Fields> const&,
|
||||||
message<isRequest, Body, Fields>,
|
typename Body::value_type const&>::value) ||
|
||||||
message<isRequest, Body, Fields> const>::type;
|
// Deprecated BodyWriter Concept (v1.66)
|
||||||
|
(std::is_constructible<typename Body::writer,
|
||||||
|
message<isRequest, Body, Fields>&>::value &&
|
||||||
|
! std::is_constructible<typename Body::writer,
|
||||||
|
message<isRequest, Body, Fields> const&>::value),
|
||||||
|
message<isRequest, Body, Fields>,
|
||||||
|
message<isRequest, Body, Fields> const>::type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -188,6 +194,8 @@ private:
|
|||||||
bool header_done_ = false;
|
bool header_done_ = false;
|
||||||
bool more_;
|
bool more_;
|
||||||
|
|
||||||
|
serializer(value_type& msg, std::true_type);
|
||||||
|
serializer(value_type& msg, std::false_type);
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
serializer(serializer&&) = default;
|
serializer(serializer&&) = default;
|
||||||
|
@@ -73,9 +73,8 @@ public:
|
|||||||
public:
|
public:
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest,
|
reader(header<isRequest, Fields>&, value_type& b)
|
||||||
span_body, Fields>& m)
|
: body_(b)
|
||||||
: body_(m.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,9 +137,8 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields> const&, value_type const& b)
|
||||||
span_body, Fields> const& msg)
|
: body_(b)
|
||||||
: body_(msg.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -81,9 +81,8 @@ public:
|
|||||||
public:
|
public:
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest,
|
reader(header<isRequest, Fields>&, value_type& b)
|
||||||
basic_string_body, Fields>& m)
|
: body_(b)
|
||||||
: body_(m.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,9 +165,8 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields> const&, value_type const& b)
|
||||||
basic_string_body, Fields> const& msg)
|
: body_(b)
|
||||||
: body_(msg.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -89,11 +89,19 @@ struct is_body_writer<T, beast::detail::void_t<
|
|||||||
std::declval<typename T::writer>().get(std::declval<error_code&>()),
|
std::declval<typename T::writer>().get(std::declval<error_code&>()),
|
||||||
(void)0)>> : std::integral_constant<bool,
|
(void)0)>> : std::integral_constant<bool,
|
||||||
boost::asio::is_const_buffer_sequence<
|
boost::asio::is_const_buffer_sequence<
|
||||||
typename T::writer::const_buffers_type>::value &&
|
typename T::writer::const_buffers_type>::value && (
|
||||||
|
(std::is_constructible<typename T::writer,
|
||||||
|
header<true, detail::fields_model>&,
|
||||||
|
typename T::value_type&>::value &&
|
||||||
std::is_constructible<typename T::writer,
|
std::is_constructible<typename T::writer,
|
||||||
|
header<false, detail::fields_model>&,
|
||||||
|
typename T::value_type&>::value) ||
|
||||||
|
// Deprecated BodyWriter Concept (v1.66)
|
||||||
|
(std::is_constructible<typename T::writer,
|
||||||
message<true, T, detail::fields_model>&>::value &&
|
message<true, T, detail::fields_model>&>::value &&
|
||||||
std::is_constructible<typename T::writer,
|
std::is_constructible<typename T::writer,
|
||||||
message<false, T, detail::fields_model>&>::value
|
message<false, T, detail::fields_model>&>::value)
|
||||||
|
)
|
||||||
> {};
|
> {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -136,11 +144,18 @@ struct is_body_reader<T, beast::detail::void_t<decltype(
|
|||||||
std::declval<typename T::reader&>().finish(
|
std::declval<typename T::reader&>().finish(
|
||||||
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::reader,
|
||||||
|
header<true, detail::fields_model>&,
|
||||||
|
typename T::value_type&>::value &&
|
||||||
std::is_constructible<typename T::reader,
|
std::is_constructible<typename T::reader,
|
||||||
|
header<false,detail::fields_model>&,
|
||||||
|
typename T::value_type&>::value) ||
|
||||||
|
// Deprecated BodyReader Concept (v1.66)
|
||||||
|
(std::is_constructible<typename T::reader,
|
||||||
message<true, T, detail::fields_model>&>::value &&
|
message<true, T, detail::fields_model>&>::value &&
|
||||||
std::is_constructible<typename T::reader,
|
std::is_constructible<typename T::reader,
|
||||||
message<false, T, detail::fields_model>&>::value
|
message<false, T, detail::fields_model>&>::value)
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@@ -76,9 +76,8 @@ public:
|
|||||||
public:
|
public:
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest,
|
reader(header<isRequest, Fields>&, value_type& b)
|
||||||
vector_body, Fields>& m)
|
: body_(b)
|
||||||
: body_(m.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,9 +154,8 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields> const&, value_type const& b)
|
||||||
vector_body, Fields> const& msg)
|
: body_(b)
|
||||||
: body_(msg.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,6 +21,7 @@ project /boost/beast/test
|
|||||||
cxx11_variadic_templates
|
cxx11_variadic_templates
|
||||||
]
|
]
|
||||||
<include>./extern
|
<include>./extern
|
||||||
|
<define>BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
;
|
;
|
||||||
|
|
||||||
path-constant ZLIB_SOURCES :
|
path-constant ZLIB_SOURCES :
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
# Official repository: https://github.com/boostorg/beast
|
# Official repository: https://github.com/boostorg/beast
|
||||||
#
|
#
|
||||||
|
|
||||||
|
add_definitions (-DBOOST_BEAST_ALLOW_DEPRECATED)
|
||||||
|
|
||||||
GroupSources(include/boost/beast beast)
|
GroupSources(include/boost/beast beast)
|
||||||
GroupSources(test/extras/include/boost/beast extras)
|
GroupSources(test/extras/include/boost/beast extras)
|
||||||
GroupSources(subtree/unit_test/include/boost/beast extras)
|
GroupSources(subtree/unit_test/include/boost/beast extras)
|
||||||
|
@@ -48,7 +48,7 @@ public:
|
|||||||
::operator delete(p);
|
::operator delete(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template<class U>
|
||||||
friend
|
friend
|
||||||
bool
|
bool
|
||||||
operator==(test_allocator<T> const&, test_allocator<U> const&) noexcept
|
operator==(test_allocator<T> const&, test_allocator<U> const&) noexcept
|
||||||
|
@@ -36,6 +36,42 @@ public:
|
|||||||
using parser_type =
|
using parser_type =
|
||||||
parser<isRequest, string_body>;
|
parser<isRequest, string_body>;
|
||||||
|
|
||||||
|
struct deprecated_body
|
||||||
|
{
|
||||||
|
using value_type = std::string;
|
||||||
|
|
||||||
|
class reader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<bool isRequest, class Fields>
|
||||||
|
explicit
|
||||||
|
reader(message<isRequest, deprecated_body, Fields>&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init(boost::optional<std::uint64_t> const&, error_code& ec)
|
||||||
|
{
|
||||||
|
ec = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
put(ConstBufferSequence const& buffers, error_code& ec)
|
||||||
|
{
|
||||||
|
ec = {};
|
||||||
|
return boost::asio::buffer_size(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
finish(error_code& ec)
|
||||||
|
{
|
||||||
|
ec = {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
boost::asio::const_buffer
|
boost::asio::const_buffer
|
||||||
buf(string_view s)
|
buf(string_view s)
|
||||||
@@ -343,6 +379,12 @@ public:
|
|||||||
BEAST_EXPECT(std::distance(m1.begin(), m1.end()) == 0);
|
BEAST_EXPECT(std::distance(m1.begin(), m1.end()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testBodyReaderCtor()
|
||||||
|
{
|
||||||
|
request_parser<deprecated_body> p;
|
||||||
|
boost::ignore_unused(p);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
@@ -351,6 +393,7 @@ public:
|
|||||||
testNeedMore<multi_buffer>();
|
testNeedMore<multi_buffer>();
|
||||||
testGotSome();
|
testGotSome();
|
||||||
testIssue818();
|
testIssue818();
|
||||||
|
testBodyReaderCtor();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -20,6 +20,40 @@ namespace http {
|
|||||||
class serializer_test : public beast::unit_test::suite
|
class serializer_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct deprecated_body
|
||||||
|
{
|
||||||
|
using value_type = std::string;
|
||||||
|
|
||||||
|
class writer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using const_buffers_type =
|
||||||
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
|
value_type const& body_;
|
||||||
|
|
||||||
|
template<bool isRequest, class Fields>
|
||||||
|
explicit
|
||||||
|
writer(message<isRequest, deprecated_body, Fields> const& m):
|
||||||
|
body_{m.body()}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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{
|
||||||
|
body_.data(), body_.size()}, false}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct const_body
|
struct const_body
|
||||||
{
|
{
|
||||||
struct value_type{};
|
struct value_type{};
|
||||||
@@ -30,7 +64,7 @@ public:
|
|||||||
boost::asio::const_buffer;
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
writer(message<isRequest, const_body, Fields> const&);
|
writer(header<isRequest, Fields> const&, value_type const&);
|
||||||
|
|
||||||
void
|
void
|
||||||
init(error_code& ec);
|
init(error_code& ec);
|
||||||
@@ -50,7 +84,7 @@ public:
|
|||||||
boost::asio::const_buffer;
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
writer(message<isRequest, mutable_body, Fields>&);
|
writer(header<isRequest, Fields>&, value_type&);
|
||||||
|
|
||||||
void
|
void
|
||||||
init(error_code& ec);
|
init(error_code& ec);
|
||||||
@@ -115,10 +149,20 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testBodyWriterCtor()
|
||||||
|
{
|
||||||
|
response<deprecated_body> res;
|
||||||
|
request<deprecated_body> req;
|
||||||
|
serializer<false, deprecated_body> sr1{res};
|
||||||
|
serializer<true, deprecated_body> sr2{req};
|
||||||
|
boost::ignore_unused(sr1, sr2);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
testWriteLimit();
|
testWriteLimit();
|
||||||
|
testBodyWriterCtor();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ struct span_body_test
|
|||||||
BEAST_EXPECT(req.body().size() == 3);
|
BEAST_EXPECT(req.body().size() == 3);
|
||||||
BEAST_EXPECT(B::size(req.body()) == 3);
|
BEAST_EXPECT(B::size(req.body()) == 3);
|
||||||
|
|
||||||
B::writer r{req};
|
B::writer r{req, req.body()};
|
||||||
error_code ec;
|
error_code ec;
|
||||||
r.init(ec);
|
r.init(ec);
|
||||||
BEAST_EXPECTS(! ec, ec.message());
|
BEAST_EXPECTS(! ec, ec.message());
|
||||||
@@ -50,7 +50,7 @@ struct span_body_test
|
|||||||
using B = span_body<char>;
|
using B = span_body<char>;
|
||||||
request<B> req;
|
request<B> req;
|
||||||
req.body() = span<char>{buf, sizeof(buf)};
|
req.body() = span<char>{buf, sizeof(buf)};
|
||||||
B::reader w{req};
|
B::reader w{req, req.body()};
|
||||||
error_code ec;
|
error_code ec;
|
||||||
w.init(boost::none, ec);
|
w.init(boost::none, ec);
|
||||||
BEAST_EXPECTS(! ec, ec.message());
|
BEAST_EXPECTS(! ec, ec.message());
|
||||||
|
@@ -48,9 +48,8 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields> const&, value_type const& b)
|
||||||
unsized_body, Fields> const& msg)
|
: body_(b)
|
||||||
: body_(msg.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,9 +92,8 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields> const&, value_type const& b)
|
||||||
test_body, Fields> const& msg)
|
: body_(b)
|
||||||
: body_(msg.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,9 +228,8 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest,
|
writer(header<isRequest, Fields> const&, value_type const& b)
|
||||||
fail_body, Fields> const& msg)
|
: body_(b)
|
||||||
: body_(msg.body())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,11 +57,12 @@ public:
|
|||||||
|
|
||||||
/** Construct the writer.
|
/** Construct the writer.
|
||||||
|
|
||||||
@param msg The message whose body is to be serialized.
|
@param h The header for the message being serialized
|
||||||
|
|
||||||
|
@param body The body being serialized
|
||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
BodyWriter(header<isRequest, Fields> const& h, value_type const& body);
|
||||||
BodyWriter(message<isRequest, Body, Fields> const& msg);
|
|
||||||
|
|
||||||
/** Initialize the writer.
|
/** Initialize the writer.
|
||||||
|
|
||||||
@@ -120,11 +121,12 @@ struct BodyReader
|
|||||||
{
|
{
|
||||||
/** Construct the reader.
|
/** Construct the reader.
|
||||||
|
|
||||||
@param msg The message whose body is to be parsed.
|
@param h The header for the message being parsed
|
||||||
|
|
||||||
|
@param body The body to store the parsed results into
|
||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Fields>
|
template<bool isRequest, class Fields>
|
||||||
explicit
|
BodyReader(header<isRequest, Fields>& h, value_type& body);
|
||||||
BodyReader(message<isRequest, Body, Fields>& msg);
|
|
||||||
|
|
||||||
/** Initialize the reader.
|
/** Initialize the reader.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user