forked from boostorg/beast
Refactor HTTP serialization and parsing (API Change):
fix #404 Parsing and serialization interfaces have been fine tuned and unified. For parsing these stream operations are defined: * read * read_header * read_some * async_read * async_read_header * async_read_some For serialization these stream operations are defined: * write * write_header * write_some * async_write * async_write_header * async_write_some
This commit is contained in:
+189
-351
@@ -21,41 +21,6 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** Describes the parser's current state.
|
||||
|
||||
The state is expressed as the type of data that
|
||||
@ref basic_parser is expecting to see in subsequently
|
||||
provided octets.
|
||||
*/
|
||||
enum class parse_state
|
||||
{
|
||||
/// Expecting one or more header octets
|
||||
header = 0,
|
||||
|
||||
/// Expecting one or more body octets
|
||||
body = 1,
|
||||
|
||||
/// Expecting zero or more body octets followed by EOF
|
||||
body_to_eof = 2,
|
||||
|
||||
/// Expecting additional chunk header octets
|
||||
chunk_header = 3,
|
||||
|
||||
/// Expecting one or more chunk body octets
|
||||
chunk_body = 4,
|
||||
|
||||
/** The parsing is complete.
|
||||
|
||||
The parse is considered complete when the full header
|
||||
is received and either the full body is received, or
|
||||
the semantics of the message indicate that no body
|
||||
is expected. This includes the case where the caller
|
||||
has indicated to the parser that no body is expected,
|
||||
for example when receiving a response to a HEAD request.
|
||||
*/
|
||||
complete = 5
|
||||
};
|
||||
|
||||
/** A parser for decoding HTTP/1 wire format messages.
|
||||
|
||||
This parser is designed to efficiently parse messages in the
|
||||
@@ -83,18 +48,13 @@ enum class parse_state
|
||||
struct derived
|
||||
: basic_parser<isRequest, derived<isRequest>>
|
||||
{
|
||||
// The type used when providing a mutable
|
||||
// buffer sequence in which to store body data.
|
||||
//
|
||||
using mutable_buffers_type = ...;
|
||||
|
||||
// When isRequest == true, called
|
||||
// after the Request Line is received.
|
||||
//
|
||||
void
|
||||
on_request(
|
||||
string_view const& method,
|
||||
string_view const& target,
|
||||
string_view method,
|
||||
string_view target,
|
||||
int version,
|
||||
error_code& ec);
|
||||
|
||||
@@ -104,7 +64,7 @@ enum class parse_state
|
||||
void
|
||||
on_response(
|
||||
int status,
|
||||
string_view const& reason,
|
||||
string_view reason,
|
||||
int version,
|
||||
error_code& ec);
|
||||
|
||||
@@ -112,8 +72,8 @@ enum class parse_state
|
||||
//
|
||||
void
|
||||
on_field(
|
||||
string_view const& name,
|
||||
string_view const& value,
|
||||
string_view name,
|
||||
string_view value,
|
||||
error_code& ec);
|
||||
|
||||
// Called after the header is complete.
|
||||
@@ -123,40 +83,19 @@ enum class parse_state
|
||||
error_code& ec);
|
||||
|
||||
// Called once before the body, if any, is started.
|
||||
// This will only be called if the semantics of the
|
||||
// message indicate that a body exists, including
|
||||
// an indicated body of zero length.
|
||||
//
|
||||
void
|
||||
on_body();
|
||||
on_body(
|
||||
boost::optional<std::uint64_t> content_length,
|
||||
error_code& ec);
|
||||
|
||||
// Called zero or more times to provide body data.
|
||||
//
|
||||
// Only used if isDirect == false
|
||||
//
|
||||
void
|
||||
on_data(
|
||||
string_view const& s,
|
||||
string_view s,
|
||||
error_code& ec);
|
||||
|
||||
// Called zero or more times to retrieve a mutable
|
||||
// buffer sequence in which to store body data.
|
||||
//
|
||||
// Only used if isDirect == true
|
||||
//
|
||||
mutable_buffers_type
|
||||
on_prepare(
|
||||
std::size_t n);
|
||||
|
||||
// Called after body data has been stored in the
|
||||
// buffer returned by the previous call to on_prepare.
|
||||
//
|
||||
// Only used if isDirect == true
|
||||
//
|
||||
void
|
||||
on_commit(
|
||||
std::size_t n);
|
||||
|
||||
// If the Transfer-Encoding is specified, and the
|
||||
// last item in the list of encodings is "chunked",
|
||||
// called after receiving a chunk header or a final
|
||||
@@ -164,8 +103,8 @@ enum class parse_state
|
||||
//
|
||||
void
|
||||
on_chunk(
|
||||
std::uint64_t length, // Length of this chunk
|
||||
string_view const& ext, // The chunk extensions, if any
|
||||
std::uint64_t length, // Length of this chunk
|
||||
string_view const& ext, // The chunk extensions, if any
|
||||
error_code& ec);
|
||||
|
||||
// Called once when the message is complete.
|
||||
@@ -177,16 +116,7 @@ enum class parse_state
|
||||
@endcode
|
||||
|
||||
If a callback sets the error code, the error will be propagated
|
||||
to the caller of the parser. Behavior of parsing after an error
|
||||
is returned is undefined.
|
||||
|
||||
When the parser state is positioned to read bytes belonging to
|
||||
the body, calling @ref write or @ref write will implicitly
|
||||
cause a buffer copy (because bytes are first transferred to the
|
||||
dynamic buffer). To avoid this copy, the additional functions
|
||||
@ref copy_body, @ref prepare_body, and @ref commit_body are
|
||||
provided to allow the caller to read bytes directly into buffers
|
||||
supplied by the parser.
|
||||
to the caller of the parser.
|
||||
|
||||
The parser is optimized for the case where the input buffer
|
||||
sequence consists of a single contiguous buffer. The
|
||||
@@ -203,26 +133,21 @@ enum class parse_state
|
||||
@tparam isRequest A `bool` indicating whether the parser will be
|
||||
presented with request or response message.
|
||||
|
||||
@tparam isDirect A `bool` indicating whether the parser interface
|
||||
supports reading body data directly into parser-provided buffers.
|
||||
|
||||
@tparam Derived The derived class type. This is part of the
|
||||
Curiously Recurring Template Pattern interface.
|
||||
*/
|
||||
template<bool isRequest, bool isDirect, class Derived>
|
||||
template<bool isRequest, class Derived>
|
||||
class basic_parser
|
||||
: private detail::basic_parser_base
|
||||
{
|
||||
template<bool OtherIsRequest,
|
||||
bool OtherIsDirect, class OtherDerived>
|
||||
template<bool OtherIsRequest, class OtherDerived>
|
||||
friend class basic_parser;
|
||||
|
||||
// Message will be complete after reading header
|
||||
static unsigned constexpr flagSkipBody = 1<< 0;
|
||||
|
||||
|
||||
|
||||
static unsigned constexpr flagOnBody = 1<< 1;
|
||||
// Consume input buffers across semantic boundaries
|
||||
static unsigned constexpr flagEager = 1<< 1;
|
||||
|
||||
// The parser has read at least one byte
|
||||
static unsigned constexpr flagGotSome = 1<< 2;
|
||||
@@ -248,10 +173,8 @@ class basic_parser
|
||||
std::size_t buf_len_ = 0;
|
||||
std::size_t skip_ = 0; // search from here
|
||||
std::size_t x_; // scratch variable
|
||||
state state_ = state::nothing_yet;
|
||||
unsigned f_ = 0; // flags
|
||||
parse_state state_ = parse_state::header;
|
||||
string_view ext_;
|
||||
string_view body_;
|
||||
|
||||
public:
|
||||
/// Copy constructor (disallowed)
|
||||
@@ -264,7 +187,8 @@ public:
|
||||
basic_parser() = default;
|
||||
|
||||
/// `true` if this parser parses requests, `false` for responses.
|
||||
static bool constexpr is_request = isRequest;
|
||||
using is_request =
|
||||
std::integral_constant<bool, isRequest>;
|
||||
|
||||
/// Destructor
|
||||
~basic_parser() = default;
|
||||
@@ -274,83 +198,70 @@ public:
|
||||
After the move, the only valid operation on the
|
||||
moved-from object is destruction.
|
||||
*/
|
||||
template<bool OtherIsDirect, class OtherDerived>
|
||||
basic_parser(basic_parser<
|
||||
isRequest, OtherIsDirect, OtherDerived>&&);
|
||||
template<class OtherDerived>
|
||||
basic_parser(basic_parser<isRequest, OtherDerived>&&);
|
||||
|
||||
/** Set the skip body option.
|
||||
/** Returns a reference to this object as a @ref basic_parser.
|
||||
|
||||
The option controls whether or not the parser expects to
|
||||
see an HTTP body, regardless of the presence or absence of
|
||||
certain fields such as Content-Length.
|
||||
|
||||
Depending on the request, some responses do not carry a body.
|
||||
For example, a 200 response to a CONNECT request from a
|
||||
tunneling proxy. In these cases, callers may use this function
|
||||
inform the parser that no body is expected. The parser will
|
||||
consider the message complete after the header has been received.
|
||||
|
||||
@note This function must called before any bytes are processed.
|
||||
This is used to pass a derived class where a base class is
|
||||
expected, to choose a correct function overload when the
|
||||
resolution would be ambiguous.
|
||||
*/
|
||||
void
|
||||
skip_body();
|
||||
|
||||
/** Returns the current parser state.
|
||||
|
||||
The parser state indicates what octets the parser
|
||||
expects to see next in the input stream.
|
||||
*/
|
||||
parse_state
|
||||
state() const
|
||||
basic_parser&
|
||||
base()
|
||||
{
|
||||
return state_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Returns a constant reference to this object as a @ref basic_parser.
|
||||
|
||||
This is used to pass a derived class where a base class is
|
||||
expected, to choose a correct function overload when the
|
||||
resolution would be ambiguous.
|
||||
*/
|
||||
basic_parser const&
|
||||
base() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Returns `true` if the parser has received at least one byte of input.
|
||||
bool
|
||||
got_some() const
|
||||
{
|
||||
return (f_ & flagGotSome) != 0;
|
||||
}
|
||||
|
||||
/// Returns `true` if the complete header has been parsed.
|
||||
bool
|
||||
got_header() const
|
||||
{
|
||||
return state_ != parse_state::header;
|
||||
}
|
||||
|
||||
/** Returns `true` if a Content-Length is specified.
|
||||
|
||||
@note Only valid after parsing a complete header.
|
||||
*/
|
||||
bool
|
||||
got_content_length() const
|
||||
{
|
||||
return (f_ & flagContentLength) != 0;
|
||||
return state_ != state::nothing_yet;
|
||||
}
|
||||
|
||||
/** Returns `true` if the message is complete.
|
||||
|
||||
The message is complete after a full header is
|
||||
parsed and one of the following is true:
|
||||
The message is complete after the full header is prduced
|
||||
and one of the following is true:
|
||||
|
||||
@li @ref skip_body was called
|
||||
@li The skip body option was set.
|
||||
|
||||
@li The semantics of the message indicate there is no body.
|
||||
|
||||
@li The semantics of the message indicate a body is
|
||||
expected, and the entire body was received.
|
||||
@li The semantics of the message indicate a body is expected,
|
||||
and the entire body was parsed.
|
||||
*/
|
||||
bool
|
||||
is_complete() const
|
||||
is_done() const
|
||||
{
|
||||
return state_ == parse_state::complete;
|
||||
return state_ == state::complete;
|
||||
}
|
||||
|
||||
/** Returns `true` if a the parser has produced the full header.
|
||||
*/
|
||||
bool
|
||||
is_header_done() const
|
||||
{
|
||||
return state_ > state::header;
|
||||
}
|
||||
|
||||
/** Returns `true` if the message is an upgrade message.
|
||||
|
||||
@note Only valid after parsing a complete header.
|
||||
@note The return value is undefined unless
|
||||
@ref is_header_done would return `true`.
|
||||
*/
|
||||
bool
|
||||
is_upgrade() const
|
||||
@@ -358,16 +269,10 @@ public:
|
||||
return (f_ & flagConnectionUpgrade) != 0;
|
||||
}
|
||||
|
||||
/** Returns `true` if keep-alive is specified
|
||||
/** Returns `true` if the last value for Transfer-Encoding is "chunked".
|
||||
|
||||
@note Only valid after parsing a complete header.
|
||||
*/
|
||||
bool
|
||||
is_keep_alive() const;
|
||||
|
||||
/** Returns `true` if the chunked Transfer-Encoding is specified.
|
||||
|
||||
@note Only valid after parsing a complete header.
|
||||
@note The return value is undefined unless
|
||||
@ref is_header_done would return `true`.
|
||||
*/
|
||||
bool
|
||||
is_chunked() const
|
||||
@@ -375,34 +280,125 @@ public:
|
||||
return (f_ & flagChunked) != 0;
|
||||
}
|
||||
|
||||
/** Write part of a buffer sequence to the parser.
|
||||
/** Returns `true` if the message has keep-alive connection semantics.
|
||||
|
||||
This function attempts to parse the HTTP message
|
||||
stored in the caller provided buffers. Upon success,
|
||||
a positive return value indicates that the parser
|
||||
@note The return value is undefined unless
|
||||
@ref is_header_done would return `true`.
|
||||
*/
|
||||
bool
|
||||
is_keep_alive() const;
|
||||
|
||||
/** Returns the optional value of Content-Length if known.
|
||||
|
||||
@note The return value is undefined unless
|
||||
@ref is_header_done would return `true`.
|
||||
*/
|
||||
boost::optional<std::uint64_t>
|
||||
content_length() const;
|
||||
|
||||
/** Returns `true` if the message semantics require an end of file.
|
||||
|
||||
Depending on the contents of the header, the parser may
|
||||
require and end of file notification to know where the end
|
||||
of the body lies. If this function returns `true` it will be
|
||||
necessary to call @ref put_eof when there will never be additional
|
||||
data from the input.
|
||||
*/
|
||||
bool
|
||||
need_eof() const
|
||||
{
|
||||
return (f_ & flagNeedEOF) != 0;
|
||||
}
|
||||
|
||||
/// Returns `true` if the eager parse option is set.
|
||||
bool
|
||||
eager() const
|
||||
{
|
||||
return (f_ & flagEager) != 0;
|
||||
}
|
||||
|
||||
/** Set the eager parse option.
|
||||
|
||||
This option controls whether or not the parser will attempt
|
||||
to consume all of the octets provided during parsing, or
|
||||
if it will stop when it reaches one of the following positions
|
||||
within the serialized message:
|
||||
|
||||
@li Immediately after the header
|
||||
|
||||
@li Immediately after any chunk header
|
||||
|
||||
The default is to stop after the header or any chunk header.
|
||||
*/
|
||||
void
|
||||
eager(bool v)
|
||||
{
|
||||
if(v)
|
||||
f_ |= flagEager;
|
||||
else
|
||||
f_ &= ~flagEager;
|
||||
}
|
||||
|
||||
/// Returns `true` if the parser will ignore the message body.
|
||||
bool
|
||||
skip()
|
||||
{
|
||||
return (f_ & flagSkipBody) != 0;
|
||||
}
|
||||
|
||||
/** Set the skip body option.
|
||||
|
||||
The option controls whether or not the parser expects to
|
||||
see an HTTP body, regardless of the presence or absence of
|
||||
certain fields such as Content-Length.
|
||||
|
||||
Depending on the request, some responses do not carry a
|
||||
body. For example, a 200 response to a CONNECT request
|
||||
from a tunneling proxy. In these cases, callers may use
|
||||
this function inform the parser that no body is expected.
|
||||
The parser will consider the message complete after the
|
||||
header has been received.
|
||||
|
||||
@note This function must called before any bytes are processed.
|
||||
*/
|
||||
void
|
||||
skip(bool v);
|
||||
|
||||
/** Write a buffer sequence to the parser.
|
||||
|
||||
This function attempts to incrementally parse the HTTP
|
||||
message data stored in the caller provided buffers. Upon
|
||||
success, a positive return value indicates that the parser
|
||||
made forward progress, consuming that number of
|
||||
bytes.
|
||||
|
||||
A return value of zero indicates that the parser
|
||||
requires additional input. In this case the caller
|
||||
should append additional bytes to the input buffer
|
||||
sequence and call @ref write again.
|
||||
In some cases there may be an insufficient number of octets
|
||||
in the input buffer in order to make forward progress. This
|
||||
is indicated by the the code @ref error::need_more. When
|
||||
this happens, the caller should place additional bytes into
|
||||
the buffer sequence and call @ref put again.
|
||||
|
||||
The error code @ref error::need_more is special. When this
|
||||
error is returned, a subsequent call to @ref put may succeed
|
||||
if the buffers have been updated. Otherwise, upon error
|
||||
the parser may not be restarted.
|
||||
|
||||
@param buffers An object meeting the requirements of
|
||||
@b ConstBufferSequence that represents the message.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
|
||||
@return The number of bytes consumed in the buffer
|
||||
sequence.
|
||||
@return The number of octets consumed in the buffer
|
||||
sequence. The caller should remove these octets even if the
|
||||
error is set.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
std::size_t
|
||||
write(ConstBufferSequence const& buffers, error_code& ec);
|
||||
put(ConstBufferSequence const& buffers, error_code& ec);
|
||||
|
||||
#if ! BEAST_DOXYGEN
|
||||
std::size_t
|
||||
write(boost::asio::const_buffers_1 const& buffer,
|
||||
put(boost::asio::const_buffers_1 const& buffer,
|
||||
error_code& ec);
|
||||
#endif
|
||||
|
||||
@@ -423,139 +419,7 @@ public:
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
write_eof(error_code& ec);
|
||||
|
||||
/** Returns the number of bytes remaining in the body or chunk.
|
||||
|
||||
If a Content-Length is specified and the parser state
|
||||
is equal to @ref beast::http::parse_state::body, this will return
|
||||
the number of bytes remaining in the body. If the
|
||||
chunked Transfer-Encoding is indicated and the parser
|
||||
state is equal to @ref beast::http::parse_state::chunk_body, this
|
||||
will return the number of bytes remaining in the chunk.
|
||||
Otherwise, the function behavior is undefined.
|
||||
*/
|
||||
std::uint64_t
|
||||
size() const
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
state_ == parse_state::body ||
|
||||
state_ == parse_state::chunk_body);
|
||||
return len_;
|
||||
}
|
||||
|
||||
/** Returns the body data parsed in the last call to @ref write.
|
||||
|
||||
This buffer is invalidated after any call to @ref write
|
||||
or @ref write_eof.
|
||||
|
||||
@note If the last call to @ref write came from the input
|
||||
area of a @b DynamicBuffer object, a call to the dynamic
|
||||
buffer's `consume` function may invalidate this return
|
||||
value.
|
||||
*/
|
||||
string_view const&
|
||||
body() const
|
||||
{
|
||||
// This function not available when isDirect==true
|
||||
BOOST_STATIC_ASSERT(! isDirect);
|
||||
return body_;
|
||||
}
|
||||
|
||||
/** Returns the chunk extension parsed in the last call to @ref write.
|
||||
|
||||
This buffer is invalidated after any call to @ref write
|
||||
or @ref write_eof.
|
||||
|
||||
@note If the last call to @ref write came from the input
|
||||
area of a @b DynamicBuffer object, a call to the dynamic
|
||||
buffer's `consume` function may invalidate this return
|
||||
value.
|
||||
*/
|
||||
string_view const&
|
||||
chunk_extension() const
|
||||
{
|
||||
// This function not available when isDirect==true
|
||||
BOOST_STATIC_ASSERT(! isDirect);
|
||||
return ext_;
|
||||
}
|
||||
|
||||
/** Returns the optional value of Content-Length if known.
|
||||
|
||||
@note The return value is undefined unless a complete
|
||||
header has been parsed.
|
||||
*/
|
||||
boost::optional<std::uint64_t>
|
||||
content_length() const
|
||||
{
|
||||
BOOST_ASSERT(got_header());
|
||||
if(! (f_ & flagContentLength))
|
||||
return boost::none;
|
||||
return len_;
|
||||
}
|
||||
|
||||
/** Copy leftover body data from the dynamic buffer.
|
||||
|
||||
@note This member function is only available when
|
||||
`isDirect==true`.
|
||||
|
||||
@return The number of bytes processed from the dynamic
|
||||
buffer. The caller should remove these bytes by calling
|
||||
`consume` on the buffer.
|
||||
*/
|
||||
template<class DynamicBuffer>
|
||||
std::size_t
|
||||
copy_body(DynamicBuffer& buffer);
|
||||
|
||||
/** Returns a set of buffers for storing body data.
|
||||
|
||||
@param buffers A writable output parameter into which
|
||||
the function will place the buffers upon success.
|
||||
|
||||
@param limit The maximum number of bytes in the
|
||||
size of the returned buffer sequence. The actual size
|
||||
of the buffer sequence may be lower than this number.
|
||||
|
||||
@note This member function is only available when
|
||||
`isDirect==true`.
|
||||
*/
|
||||
template<class MutableBufferSequence>
|
||||
void
|
||||
prepare_body(boost::optional<
|
||||
MutableBufferSequence>& buffers, std::size_t limit);
|
||||
|
||||
/** Commit body data.
|
||||
|
||||
@param n The number of bytes to commit. This must
|
||||
be less than or equal to the size of the buffer
|
||||
sequence returned by @ref prepare_body.
|
||||
|
||||
@note This member function is only available when
|
||||
`isDirect==true`.
|
||||
*/
|
||||
void
|
||||
commit_body(std::size_t n);
|
||||
|
||||
/** Indicate that body octets have been consumed.
|
||||
|
||||
@param n The number of bytes to consume.
|
||||
*/
|
||||
void
|
||||
consume(std::size_t n)
|
||||
{
|
||||
BOOST_ASSERT(n <= len_);
|
||||
BOOST_ASSERT(
|
||||
state_ == parse_state::body ||
|
||||
state_ == parse_state::chunk_body);
|
||||
len_ -= n;
|
||||
if(len_ == 0)
|
||||
{
|
||||
if(state_ == parse_state::body)
|
||||
state_ = parse_state::complete;
|
||||
else
|
||||
state_ = parse_state::chunk_header;
|
||||
}
|
||||
}
|
||||
put_eof(error_code& ec);
|
||||
|
||||
private:
|
||||
inline
|
||||
@@ -570,68 +434,42 @@ private:
|
||||
maybe_flatten(
|
||||
ConstBufferSequence const& buffers);
|
||||
|
||||
std::size_t
|
||||
do_write(boost::asio::const_buffers_1 const& buffer,
|
||||
void
|
||||
parse_header(char const*& p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
void
|
||||
parse_header(char const*& p, char const* term,
|
||||
error_code& ec, std::true_type);
|
||||
|
||||
std::size_t
|
||||
do_write(boost::asio::const_buffers_1 const& buffer,
|
||||
void
|
||||
parse_header(char const*& p, char const* term,
|
||||
error_code& ec, std::false_type);
|
||||
|
||||
void
|
||||
parse_startline(char const*& it,
|
||||
int& version, int& status,
|
||||
error_code& ec, std::true_type);
|
||||
parse_body(char const*& p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
void
|
||||
parse_startline(char const*& it,
|
||||
int& version, int& status,
|
||||
error_code& ec, std::false_type);
|
||||
parse_body_to_eof(char const*& p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
void
|
||||
parse_fields(char const*& it,
|
||||
parse_chunk_header(char const*& p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
void
|
||||
parse_chunk_body(char const*& p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
void
|
||||
parse_fields(char const*& p,
|
||||
char const* last, error_code& ec);
|
||||
|
||||
void
|
||||
do_field(
|
||||
string_view const& name,
|
||||
string_view const& value,
|
||||
error_code& ec);
|
||||
|
||||
std::size_t
|
||||
parse_header(char const* p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
void
|
||||
do_header(int, std::true_type);
|
||||
|
||||
void
|
||||
do_header(int status, std::false_type);
|
||||
|
||||
void
|
||||
maybe_do_body_direct();
|
||||
|
||||
void
|
||||
maybe_do_body_indirect(error_code& ec);
|
||||
|
||||
std::size_t
|
||||
parse_chunk_header(char const* p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
std::size_t
|
||||
parse_body(char const* p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
std::size_t
|
||||
parse_body_to_eof(char const* p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
std::size_t
|
||||
parse_chunk_body(char const* p,
|
||||
std::size_t n, error_code& ec);
|
||||
|
||||
void
|
||||
do_complete(error_code& ec);
|
||||
do_field(string_view const& name,
|
||||
string_view const& value,
|
||||
error_code& ec);
|
||||
};
|
||||
|
||||
} // http
|
||||
|
||||
Reference in New Issue
Block a user