mirror of
https://github.com/boostorg/beast.git
synced 2025-08-01 22:04:34 +02:00
Add on_body_what parser callback (API Change):
These changes support parsing the headers separately from the body. * on_headers now returns void * on_body_what is a new required callback which returns body_what
This commit is contained in:
@@ -23,6 +23,8 @@ API Changes:
|
|||||||
- Add has_reader, has_writer, is_Reader, is_Writer
|
- Add has_reader, has_writer, is_Reader, is_Writer
|
||||||
- More friendly compile errors on failed concept checks
|
- More friendly compile errors on failed concept checks
|
||||||
* basic_parser_v1 requires all callbacks present
|
* basic_parser_v1 requires all callbacks present
|
||||||
|
* on_headers parser callback now returns void
|
||||||
|
* on_body_what is a new required parser callback returning body_what
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -103,17 +103,17 @@ enum class body_what
|
|||||||
|
|
||||||
/** The message represents an UPGRADE request.
|
/** The message represents an UPGRADE request.
|
||||||
|
|
||||||
When returned by `on_headers` this causes parsing
|
When returned by `on_body_prepare` this causes parsing
|
||||||
to complete and control to return to the caller.
|
to complete and control to return to the caller.
|
||||||
*/
|
*/
|
||||||
upgrade,
|
upgrade,
|
||||||
|
|
||||||
/** Suspend parsing before reading the body.
|
/** Suspend parsing before reading the body.
|
||||||
|
|
||||||
When returned by `on_headers` this causes parsing to
|
When returned by `on_body_prepare` this causes parsing
|
||||||
pause. Control is returned to the caller, and the parser
|
to pause. Control is returned to the caller, and the
|
||||||
state is preserved such that a subsequent call to the
|
parser state is preserved such that a subsequent call
|
||||||
parser will begin reading the message body.
|
to the parser will begin reading the message body.
|
||||||
|
|
||||||
This could be used by callers to inspect the HTTP
|
This could be used by callers to inspect the HTTP
|
||||||
headers before committing to read the body. For example,
|
headers before committing to read the body. For example,
|
||||||
@@ -183,9 +183,14 @@ static std::uint64_t constexpr no_content_length =
|
|||||||
|
|
||||||
// Called when all the headers have been parsed successfully.
|
// Called when all the headers have been parsed successfully.
|
||||||
//
|
//
|
||||||
body_what
|
void
|
||||||
on_headers(std::uint64_t content_length, error_code&);
|
on_headers(std::uint64_t content_length, error_code&);
|
||||||
|
|
||||||
|
// Called after on_headers, before the body is parsed
|
||||||
|
//
|
||||||
|
body_what
|
||||||
|
on_body_what(std::uint64_t content_length, error_code&);
|
||||||
|
|
||||||
// Called for each piece of the body.
|
// Called for each piece of the body.
|
||||||
//
|
//
|
||||||
// If the headers indicate chunk encoding, the chunk
|
// If the headers indicate chunk encoding, the chunk
|
||||||
@@ -203,9 +208,9 @@ static std::uint64_t constexpr no_content_length =
|
|||||||
};
|
};
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The return value of `on_headers` is special, it controls whether
|
The return value of `on_body_what` is special, it controls
|
||||||
or not the parser should expect a body. See @ref body_what for
|
whether or not the parser should expect a body. See @ref body_what
|
||||||
choices of the return value.
|
for choices of the return value.
|
||||||
|
|
||||||
If a callback sets an error, parsing stops at the current octet
|
If a callback sets an error, parsing stops at the current octet
|
||||||
and the error is returned to the caller. Callbacks must not throw
|
and the error is returned to the caller. Callbacks must not throw
|
||||||
@@ -595,12 +600,22 @@ private:
|
|||||||
std::declval<error_code&>())
|
std::declval<error_code&>())
|
||||||
)>> : std::true_type {};
|
)>> : std::true_type {};
|
||||||
|
|
||||||
|
template<class T, class = beast::detail::void_t<>>
|
||||||
|
struct check_on_headers : std::false_type {};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct check_on_headers<T, beast::detail::void_t<decltype(
|
||||||
|
std::declval<T>().on_headers(
|
||||||
|
std::declval<std::uint64_t>(),
|
||||||
|
std::declval<error_code&>())
|
||||||
|
)>> : std::true_type {};
|
||||||
|
|
||||||
// VFALCO Can we use std::is_detected? Is C++11 capable?
|
// VFALCO Can we use std::is_detected? Is C++11 capable?
|
||||||
template<class C>
|
template<class C>
|
||||||
class check_on_headers_t
|
class check_on_body_what_t
|
||||||
{
|
{
|
||||||
template<class T, class R = std::is_convertible<decltype(
|
template<class T, class R = std::is_convertible<decltype(
|
||||||
std::declval<T>().on_headers(
|
std::declval<T>().on_body_what(
|
||||||
std::declval<std::uint64_t>(),
|
std::declval<std::uint64_t>(),
|
||||||
std::declval<error_code&>())),
|
std::declval<error_code&>())),
|
||||||
body_what>>
|
body_what>>
|
||||||
@@ -612,8 +627,8 @@ private:
|
|||||||
static bool const value = type::value;
|
static bool const value = type::value;
|
||||||
};
|
};
|
||||||
template<class C>
|
template<class C>
|
||||||
using check_on_headers =
|
using check_on_body_what =
|
||||||
std::integral_constant<bool, check_on_headers_t<C>::value>;
|
std::integral_constant<bool, check_on_body_what_t<C>::value>;
|
||||||
|
|
||||||
template<class T, class = beast::detail::void_t<>>
|
template<class T, class = beast::detail::void_t<>>
|
||||||
struct check_on_body : std::false_type {};
|
struct check_on_body : std::false_type {};
|
||||||
@@ -780,12 +795,20 @@ private:
|
|||||||
impl().on_value(s, ec);
|
impl().on_value(s, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
body_what
|
void
|
||||||
call_on_headers(error_code& ec)
|
call_on_headers(error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(check_on_headers<Derived>::value,
|
static_assert(check_on_headers<Derived>::value,
|
||||||
"on_headers requirements not met");
|
"on_headers requirements not met");
|
||||||
return impl().on_headers(content_length_, ec);
|
impl().on_headers(content_length_, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
body_what
|
||||||
|
call_on_body_what(error_code& ec)
|
||||||
|
{
|
||||||
|
static_assert(check_on_body_what<Derived>::value,
|
||||||
|
"on_body_what requirements not met");
|
||||||
|
return impl().on_body_what(content_length_, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void call_on_body(error_code& ec,
|
void call_on_body(error_code& ec,
|
||||||
|
@@ -127,6 +127,7 @@ protected:
|
|||||||
s_chunk_data_cr,
|
s_chunk_data_cr,
|
||||||
s_chunk_data_lf,
|
s_chunk_data_lf,
|
||||||
|
|
||||||
|
s_body_what,
|
||||||
s_body_identity0,
|
s_body_identity0,
|
||||||
s_body_identity,
|
s_body_identity,
|
||||||
s_body_identity_eof0,
|
s_body_identity_eof0,
|
||||||
|
@@ -899,7 +899,16 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
|
|||||||
return err(parse_error::illegal_content_length);
|
return err(parse_error::illegal_content_length);
|
||||||
upgrade_ = ((flags_ & (parse_flag::upgrade | parse_flag::connection_upgrade)) ==
|
upgrade_ = ((flags_ & (parse_flag::upgrade | parse_flag::connection_upgrade)) ==
|
||||||
(parse_flag::upgrade | parse_flag::connection_upgrade)) /*|| method == "connect"*/;
|
(parse_flag::upgrade | parse_flag::connection_upgrade)) /*|| method == "connect"*/;
|
||||||
auto const what = call_on_headers(ec);
|
call_on_headers(ec);
|
||||||
|
if(ec)
|
||||||
|
return errc();
|
||||||
|
s_ = s_body_what;
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
|
||||||
|
case s_body_what:
|
||||||
|
{
|
||||||
|
auto const what = call_on_body_what(ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return errc();
|
return errc();
|
||||||
switch(what)
|
switch(what)
|
||||||
@@ -913,7 +922,6 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
|
|||||||
flags_ |= parse_flag::skipbody;
|
flags_ |= parse_flag::skipbody;
|
||||||
break;
|
break;
|
||||||
case body_what::pause:
|
case body_what::pause:
|
||||||
s_ = s_headers_done;
|
|
||||||
return used();
|
return used();
|
||||||
}
|
}
|
||||||
s_ = s_headers_done;
|
s_ = s_headers_done;
|
||||||
|
@@ -241,11 +241,16 @@ private:
|
|||||||
m_.reason = std::move(this->reason_);
|
m_.reason = std::move(this->reason_);
|
||||||
}
|
}
|
||||||
|
|
||||||
body_what
|
void
|
||||||
on_headers(std::uint64_t, error_code& ec)
|
on_headers(std::uint64_t, error_code& ec)
|
||||||
{
|
{
|
||||||
flush();
|
flush();
|
||||||
m_.version = 10 * this->http_major() + this->http_minor();
|
m_.version = 10 * this->http_major() + this->http_minor();
|
||||||
|
}
|
||||||
|
|
||||||
|
body_what
|
||||||
|
on_body_what(std::uint64_t, error_code& ec)
|
||||||
|
{
|
||||||
if(skip_body_)
|
if(skip_body_)
|
||||||
return body_what::skip;
|
return body_what::skip;
|
||||||
r_.emplace(m_);
|
r_.emplace(m_);
|
||||||
|
@@ -52,6 +52,7 @@ public:
|
|||||||
bool field = false;
|
bool field = false;
|
||||||
bool value = false;
|
bool value = false;
|
||||||
bool headers = false;
|
bool headers = false;
|
||||||
|
bool _body_what = false;
|
||||||
bool body = false;
|
bool body = false;
|
||||||
bool complete = false;
|
bool complete = false;
|
||||||
|
|
||||||
@@ -90,10 +91,15 @@ public:
|
|||||||
{
|
{
|
||||||
value = true;
|
value = true;
|
||||||
}
|
}
|
||||||
body_what
|
void
|
||||||
on_headers(std::uint64_t, error_code&)
|
on_headers(std::uint64_t, error_code&)
|
||||||
{
|
{
|
||||||
headers = true;
|
headers = true;
|
||||||
|
}
|
||||||
|
body_what
|
||||||
|
on_body_what(std::uint64_t, error_code&)
|
||||||
|
{
|
||||||
|
_body_what = true;
|
||||||
return body_what::normal;
|
return body_what::normal;
|
||||||
}
|
}
|
||||||
void on_body(boost::string_ref const&, error_code&)
|
void on_body(boost::string_ref const&, error_code&)
|
||||||
@@ -130,6 +136,7 @@ public:
|
|||||||
BEAST_EXPECT(p.field);
|
BEAST_EXPECT(p.field);
|
||||||
BEAST_EXPECT(p.value);
|
BEAST_EXPECT(p.value);
|
||||||
BEAST_EXPECT(p.headers);
|
BEAST_EXPECT(p.headers);
|
||||||
|
BEAST_EXPECT(p._body_what);
|
||||||
BEAST_EXPECT(p.body);
|
BEAST_EXPECT(p.body);
|
||||||
BEAST_EXPECT(p.complete);
|
BEAST_EXPECT(p.complete);
|
||||||
}
|
}
|
||||||
|
@@ -85,8 +85,15 @@ public:
|
|||||||
fc_.fail(ec);
|
fc_.fail(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
body_what
|
void
|
||||||
on_headers(std::uint64_t content_length, error_code& ec)
|
on_headers(std::uint64_t content_length, error_code& ec)
|
||||||
|
{
|
||||||
|
if(fc_.fail(ec))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
body_what
|
||||||
|
on_body_what(std::uint64_t content_length, error_code& ec)
|
||||||
{
|
{
|
||||||
if(fc_.fail(ec))
|
if(fc_.fail(ec))
|
||||||
return body_what::normal;
|
return body_what::normal;
|
||||||
|
Reference in New Issue
Block a user