parser requires basic_fields (API Change):

* `parser` is now templated on Allocator

* `parser` only produces messages using `basic_fields<Allocator>`
  as the Fields type.

* message-oriented read and async_read only work on messages
  using basic_fields as the Fields type.

Actions Required:

* Callers using `parser` with Fields types other than basic_fields
  will need to create their own subclass of basic_parser to work
  with their custom fields type.
This commit is contained in:
Vinnie Falco
2017-06-19 11:54:53 -07:00
parent 72ce21927c
commit 50902c3938
7 changed files with 68 additions and 52 deletions

View File

@@ -8,6 +8,16 @@ Version 62:
* Clear the error faster
* Avoid explicit operator bool for error
API Changes:
* parser requires basic_fields
Actions Required:
* Callers using `parser` with Fields types other than basic_fields
will need to create their own subclass of basic_parser to work
with their custom fields type.
--------------------------------------------------------------------------------
Version 61:

View File

@@ -464,7 +464,6 @@ do_head_request(
*/
template<
bool isRequest,
class Fields = fields,
class SyncWriteStream,
class SyncReadStream,
class DynamicBuffer,
@@ -487,10 +486,10 @@ relay(
char buf[2048];
// Create a parser with a buffer body to read from the input.
parser<isRequest, buffer_body, Fields> p;
parser<isRequest, buffer_body> p;
// Create a serializer from the message contained in the parser.
serializer<isRequest, buffer_body, Fields> sr{p.get()};
serializer<isRequest, buffer_body, fields> sr{p.get()};
// Read just the header from the input
read_header(input, buffer, p, ec);
@@ -684,13 +683,12 @@ write_ostream(
template<
class Allocator,
bool isRequest,
class Body,
class Fields>
class Body>
void
read_istream(
std::istream& is,
basic_flat_buffer<Allocator>& buffer,
message<isRequest, Body, Fields>& msg,
message<isRequest, Body, fields>& msg,
error_code& ec)
{
// Create the message parser
@@ -700,7 +698,7 @@ read_istream(
// a move construction in case the caller has constructed
// their message in a non-default way.
//
parser<isRequest, Body, Fields> p{std::move(msg)};
parser<isRequest, Body> p{std::move(msg)};
do
{

View File

@@ -14,19 +14,19 @@
namespace beast {
namespace http {
template<bool isRequest, class Body, class Fields>
template<bool isRequest, class Body, class Allocator>
template<class Arg1, class... ArgN, class>
parser<isRequest, Body, Fields>::
parser<isRequest, Body, Allocator>::
parser(Arg1&& arg1, ArgN&&... argn)
: m_(std::forward<Arg1>(arg1),
std::forward<ArgN>(argn)...)
{
}
template<bool isRequest, class Body, class Fields>
template<bool isRequest, class Body, class Allocator>
template<class OtherBody, class... Args, class>
parser<isRequest, Body, Fields>::
parser(parser<isRequest, OtherBody, Fields>&& p,
parser<isRequest, Body, Allocator>::
parser(parser<isRequest, OtherBody, Allocator>&& p,
Args&&... args)
: base_type(std::move(p))
, m_(p.release(), std::forward<Args>(args)...)

View File

@@ -300,15 +300,15 @@ upcall:
//------------------------------------------------------------------------------
template<class Stream, class DynamicBuffer,
bool isRequest, class Body, class Fields,
bool isRequest, class Body, class Allocator,
class Handler>
class read_msg_op
{
using parser_type =
parser<isRequest, Body, Fields>;
parser<isRequest, Body, Allocator>;
using message_type =
message<isRequest, Body, Fields>;
typename parser_type::value_type;
struct data
{
@@ -383,11 +383,11 @@ public:
};
template<class Stream, class DynamicBuffer,
bool isRequest, class Body, class Fields,
bool isRequest, class Body, class Allocator,
class Handler>
void
read_msg_op<Stream, DynamicBuffer,
isRequest, Body, Fields, Handler>::
isRequest, Body, Allocator, Handler>::
operator()(error_code ec)
{
auto& d = *d_;
@@ -693,12 +693,12 @@ async_read(
template<
class SyncReadStream,
class DynamicBuffer,
bool isRequest, class Body, class Fields>
bool isRequest, class Body, class Allocator>
void
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
message<isRequest, Body, Fields>& msg)
message<isRequest, Body, basic_fields<Allocator>>& msg)
{
static_assert(is_sync_read_stream<SyncReadStream>::value,
"SyncReadStream requirements not met");
@@ -717,12 +717,12 @@ read(
template<
class SyncReadStream,
class DynamicBuffer,
bool isRequest, class Body, class Fields>
bool isRequest, class Body, class Allocator>
void
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
message<isRequest, Body, Fields>& msg,
message<isRequest, Body, basic_fields<Allocator>>& msg,
error_code& ec)
{
static_assert(is_sync_read_stream<SyncReadStream>::value,
@@ -733,7 +733,7 @@ read(
"Body requirements not met");
static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met");
parser<isRequest, Body, Fields> p{std::move(msg)};
parser<isRequest, Body, Allocator> p{std::move(msg)};
p.eager(true);
read(stream, buffer, p.base(), ec);
if(ec)
@@ -744,13 +744,13 @@ read(
template<
class AsyncReadStream,
class DynamicBuffer,
bool isRequest, class Body, class Fields,
bool isRequest, class Body, class Allocator,
class ReadHandler>
async_return_type<ReadHandler, void(error_code)>
async_read(
AsyncReadStream& stream,
DynamicBuffer& buffer,
message<isRequest, Body, Fields>& msg,
message<isRequest, Body, basic_fields<Allocator>>& msg,
ReadHandler&& handler)
{
static_assert(is_async_read_stream<AsyncReadStream>::value,
@@ -764,7 +764,7 @@ async_read(
async_completion<ReadHandler,
void(error_code)> init{handler};
detail::read_msg_op<AsyncReadStream, DynamicBuffer,
isRequest, Body, Fields, handler_type<
isRequest, Body, Allocator, handler_type<
ReadHandler, void(error_code)>>{
init.completion_handler, stream, buffer, msg}(
error_code{});

View File

@@ -14,6 +14,7 @@
#include <beast/http/type_traits.hpp>
#include <boost/optional.hpp>
#include <boost/throw_exception.hpp>
#include <memory>
#include <type_traits>
#include <utility>
@@ -23,24 +24,27 @@ namespace http {
/** An HTTP/1 parser for producing a message.
This class uses the basic HTTP/1 wire format parser to convert
a series of octets into a @ref message.
a series of octets into a @ref message using the @ref basic_fields
container to represent the fields.
@tparam isRequest Indicates whether a request or response
will be parsed.
@tparam Body The type used to represent the body.
@tparam Body The type used to represent the body. This must
meet the requirements of @b Body.
@tparam Fields The type of container used to represent the fields.
@tparam Allocator The type of allocator used with the
@ref basic_fields container.
@note A new instance of the parser is required for each message.
*/
template<
bool isRequest,
class Body,
class Fields = fields>
class Allocator = std::allocator<char>>
class parser
: public basic_parser<isRequest,
parser<isRequest, Body, Fields>>
parser<isRequest, Body, Allocator>>
{
static_assert(is_body<Body>::value,
"Body requirements not met");
@@ -52,14 +56,15 @@ class parser
friend class parser;
using base_type = basic_parser<isRequest,
parser<isRequest, Body, Fields>>;
parser<isRequest, Body, Allocator>>;
message<isRequest, Body, Fields> m_;
message<isRequest, Body, basic_fields<Allocator>> m_;
boost::optional<typename Body::writer> wr_;
public:
/// The type of message returned by the parser
using value_type = message<isRequest, Body, Fields>;
using value_type =
message<isRequest, Body, basic_fields<Allocator>>;
/// Constructor (default)
parser() = default;
@@ -126,6 +131,9 @@ public:
@throws std::invalid_argument Thrown when the constructed-from
parser has already initialized a body writer.
@note This function participates in overload resolution only
if the other parser uses a different body type.
*/
#if BEAST_DOXYGEN
template<class OtherBody, class... Args>
@@ -135,13 +143,13 @@ public:
! std::is_same<Body, OtherBody>::value>::type>
#endif
explicit
parser(parser<isRequest, OtherBody, Fields>&& parser,
Args&&... args);
parser(parser<isRequest, OtherBody,
Allocator>&& parser, Args&&... args);
/** Returns the parsed message.
Depending on the progress of the parser, portions
of this object may be incomplete.
Depending on the parser's progress,
parts of this object may be incomplete.
*/
value_type const&
get() const
@@ -151,8 +159,8 @@ public:
/** Returns the parsed message.
Depending on the progress of the parser, portions
of this object may be incomplete.
Depending on the parser's progress,
parts of this object may be incomplete.
*/
value_type&
get()
@@ -163,8 +171,8 @@ public:
/** Returns ownership of the parsed message.
Ownership is transferred to the caller.
Depending on the progress of the parser, portions
of this object may be incomplete.
Depending on the parser's progress,
parts of this object may be incomplete.
@par Requires
@@ -253,12 +261,12 @@ private:
};
/// An HTTP/1 parser for producing a request message.
template<class Body, class Fields = fields>
using request_parser = parser<true, Body, Fields>;
template<class Body, class Allocator = std::allocator<char>>
using request_parser = parser<true, Body, Allocator>;
/// An HTTP/1 parser for producing a response message.
template<class Body, class Fields = fields>
using response_parser = parser<false, Body, Fields>;
template<class Body, class Allocator = std::allocator<char>>
using response_parser = parser<false, Body, Allocator>;
} // http
} // beast

View File

@@ -614,12 +614,12 @@ async_read(
template<
class SyncReadStream,
class DynamicBuffer,
bool isRequest, class Body, class Fields>
bool isRequest, class Body, class Allocator>
void
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
message<isRequest, Body, Fields>& msg);
message<isRequest, Body, basic_fields<Allocator>>& msg);
/** Read a complete message from a stream.
@@ -666,12 +666,12 @@ read(
template<
class SyncReadStream,
class DynamicBuffer,
bool isRequest, class Body, class Fields>
bool isRequest, class Body, class Allocator>
void
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
message<isRequest, Body, Fields>& msg,
message<isRequest, Body, basic_fields<Allocator>>& msg,
error_code& ec);
/** Read a complete message from a stream asynchronously.
@@ -735,7 +735,7 @@ read(
template<
class AsyncReadStream,
class DynamicBuffer,
bool isRequest, class Body, class Fields,
bool isRequest, class Body, class Allocator,
class ReadHandler>
#if BEAST_DOXYGEN
void_or_deduced
@@ -746,7 +746,7 @@ async_return_type<
async_read(
AsyncReadStream& stream,
DynamicBuffer& buffer,
message<isRequest, Body, Fields>& msg,
message<isRequest, Body, basic_fields<Allocator>>& msg,
ReadHandler&& handler);
} // http

View File

@@ -32,7 +32,7 @@ class parser_test
public:
template<bool isRequest>
using parser_type =
parser<isRequest, string_body, fields>;
parser<isRequest, string_body>;
static
boost::asio::const_buffers_1