Beast Logo

PrevUpHomeNext

Parser Stream Operations

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 19. Parser

Name

Description

parser

/// 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<...>;

request_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>;

response_parser

/// 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] Note

The basic_parser and classes derived from it handle octet streams serialized in the HTTP/1 format described in rfc7230.

The stream operations which work on parsers are:

Table 20. Parser Stream Operations

Name

Description

read

Read everything into a parser from a SyncWriteStream.

async_read

Read everything into a parser asynchronously from an AsyncWriteStream.

read_header

Read only the header octets into a parser from a SyncWriteStream.

async_read_header

Read only the header octets into a parser asynchronously from an AsyncWriteStream.

read_some

Read some octets into a parser from a SyncReadStream.

async_read_some

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 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;
}

PrevUpHomeNext