...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Non-trivial algorithms need to do more than receive entire messages at once, such as:
These types of operations require callers to manage the lifetime of associated
state, by constructing a class derived from basic_parser
. Beast comes with the
derived instance parser
which creates complete message
objects using the basic_fields
Fields container.
Table 1.22. Parser
Name |
Description |
---|---|
/// An HTTP/1 parser for producing a message. template< bool isRequest, // `true` to parse an HTTP request class Body, // The Body type for the resulting message class Allocator = std::allocator<char>> // The type of allocator for the header class parser : public basic_parser<...>; |
|
/// An HTTP/1 parser for producing a request message. 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 Allocator = std::allocator<char>> using response_parser = parser<false, Body, Allocator>; |
Note | |
---|---|
The |
The stream operations which work on parsers are:
Table 1.23. Parser Stream Operations
Name |
Description |
---|---|
Read everything into a parser from a SyncWriteStream. |
|
Read everything into a parser asynchronously from an AsyncWriteStream. |
|
Read only the header octets into a parser from a SyncWriteStream. |
|
Read only the header octets into a parser asynchronously from an AsyncWriteStream. |
|
Read some octets into a parser from a SyncReadStream. |
|
Read some octets into a parser asynchronously from an AsyncWriteStream. |
As with message stream operations, parser stream operations require a persisted
DynamicBuffer
for holding unused octets from the stream. The basic parser implementation
is optimized for the case where this dynamic buffer stores its input sequence
in a single contiguous memory buffer. It is advised to use an instance of
flat_buffer
,
flat_static_buffer
, or flat_static_buffer_base
for this
purpose, although a user defined instance of DynamicBuffer
which produces input sequences of length one is also suitable.
The parser contains a message constructed internally. Arguments passed to
the parser's constructor are forwarded into the message container. The caller
can access the message inside the parser by calling parser::get
. If the Fields
and Body
types are MoveConstructible, the caller can take ownership of
the message by calling parser::release
. In this example we read
an HTTP response with a string body using a parser, then print the response:
template<class SyncReadStream> void print_response(SyncReadStream& stream) { static_assert(is_sync_read_stream<SyncReadStream>::value, "SyncReadStream type requirements not met"); // Declare a parser for an HTTP response response_parser<string_body> parser; // Read the entire message read(stream, parser); // Now print the message std::cout << parser.get() << std::endl; }