Documentation work

This commit is contained in:
Vinnie Falco
2017-06-03 09:45:09 -07:00
parent 00667f3cf2
commit 78d9e3bbce
11 changed files with 665 additions and 351 deletions

View File

@@ -93,9 +93,13 @@ of redirects, gzipped transfer encodings, caching, or proxying (to name
a few) are not directly provided, but nothing stops users from creating
these features using Beast's HTTP message types.
The library is intended to be the foundation upon which other networking
libraries are built. It is a goal that other architects will build
interoperable solutions on top of Beast.
[important
Beast is not an HTTP client or HTTP server, but it can be used to
build both. The library is intended to be a foundation upon which
new libraries may be built. It is a goal that other architects will
build interoperable solutions on top of Beast. The provided example
code shows how a client or server may be built.
]
[heading Credits]

View File

@@ -80,14 +80,14 @@ The stream operations which work on parsers are:
[table Parser Stream Operations
[[Name][Description]]
[[
[link beast.ref.http__read_some.overload1 [*read_some]]
[link beast.ref.http__read.overload1 [*read]]
][
Read some octets into a parser from a __SyncReadStream__.
Read everything into a parser from a __SyncWriteStream__.
]]
[[
[link beast.ref.http__async_read_some [*async_read_some]]
[link beast.ref.http__async_read.overload1 [*async_read]]
][
Read some octets into a parser asynchronously from an __AsyncWriteStream__.
Read everything into a parser asynchronously from an __AsyncWriteStream__.
]]
[[
[link beast.ref.http__read_header.overload1 [*read_header]]
@@ -100,14 +100,14 @@ The stream operations which work on parsers are:
Read only the header octets into a parser asynchronously from an __AsyncWriteStream__.
]]
[[
[link beast.ref.http__read.overload1 [*read]]
[link beast.ref.http__read_some.overload1 [*read_some]]
][
Read everything into a parser from a __SyncWriteStream__.
Read some octets into a parser from a __SyncReadStream__.
]]
[[
[link beast.ref.http__async_read.overload1 [*async_read]]
[link beast.ref.http__async_read_some [*async_read_some]]
][
Read everything into a parser asynchronously from an __AsyncWriteStream__.
Read some octets into a parser asynchronously from an __AsyncWriteStream__.
]]
]

View File

@@ -12,7 +12,6 @@ and invoke its methods directly instead of using the provided stream
algorithms. This could be useful for implementing algorithms on streams
whose interface does not conform to __Stream__. For example, a
[@https://github.com/libuv/libuv *libuv* socket].
The serializer interface is interactive; the caller invokes it repeatedly to
produce buffers until all of the buffers have been generated. Then the
serializer is destroyed.

View File

@@ -13,7 +13,6 @@ invoke its methods directly instead of using the provided stream algorithms.
This could be useful for implementing algorithms on streams whose interface
does not conform to any __Stream__. For example, a
[@http://zeromq.org/ *ZeroMQ* socket].
The basic parser interface is interactive; the caller invokes the function
[link beast.ref.http__basic_parser.put `basic_parser::put`]
repeatedly with buffers until an error occurs or the parsing is done. The
@@ -22,9 +21,44 @@ function
Is used when the caller knows that there will never be more data (for example,
if the underlying connection is closed),
[heading Split Parsing]
[heading Parser Options]
[heading Eager Parsing]
The parser provides two options which may be set before parsing begins:
[table Parser Options
[[Name][Default][Description]]
[[
[link beast.ref.http__basic_parser.eager.overload2 `eager`]
][
`false`
][
Normally the parser returns after successfully parsing a structured
element (header, chunk header, or chunk body) even if there are octets
remaining in the input. This is necessary when attempting to parse the
header first, or when the caller wants to inspect information which may
be invalidated by subsequent parsing, such as a chunk extension. The
`eager` option controls whether the parser keeps going after parsing
structured element if there are octets remaining in the buffer and no
error occurs. This option is automatically set or cleared during certain
stream operations to improve performance with no change in functionality.
]]
[[
[link beast.ref.http__basic_parser.skip.overload2 `skip`]
][
`false`
][
This 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 or a chunked Transfer-Encoding. Depending on the request,
some responses do not carry a body. For example, a 200 response to a
[@https://tools.ietf.org/html/rfc7231#section-4.3.6 CONNECT] request
from a tunneling proxy, or a response to a
[@https://tools.ietf.org/html/rfc7231#section-4.3.2 HEAD] request.
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.
]]
]
[heading Example: Parsing from a std::istream]

View File

@@ -7,4 +7,103 @@
[section:custom_parsers Custom Parsers]
While the parsers included in the library will handle a broad number of
use-cases, the __basic_parser__ interface can be subclassed to implement
custom parsing strategies: the parser processes the incoming octets into
elements according to the HTTP/1 protocol specification, while the derived
class decides what to do with those elements. In particular, users who
create exotic containers for [*Fields] may need to also create their own
parser. Custom parsers will work with all of the stream read operations
that work on parsers, as those algorithms use only the basic parser interface.
The basic parser uses the Curiously Recurring Template Pattern
([@https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern CRTP]).
To declare your user defined parser, first derive it from __basic_parser__:
```
template<bool isRequest>
class custom_parser
: public basic_parser<isRequest, custom_parser<isRequest>>
{
friend class basic_parser<isRequest, custom_parser>;
...
```
The interface to the parser is event-driven. Member functions of the derived
class (termed "callbacks" in this context) are invoked with parsed elements
as they become available, requiring either the `friend` declaration as shown
above or that the member functions are declared public (not recommended).
Buffers provided by the parser are non-owning references, it is the
responsibility of the derived class to copy any information it needs before
returning from the callback.
```
template<bool isRequest>
class custom_parser
: public basic_parser<isRequest, custom_parser<isRequest>>
{
friend class basic_parser<isRequest, custom_parser>;
/// Called after receiving the request-line (isRequest == true).
void
on_request(
string_view method, // The method
string_view target, // The request-target
int version, // The HTTP-version
error_code& ec); // The error returned to the caller, if any
/// Called after receiving the start-line (isRequest == false).
void
on_response(
int status, // The status-code
string_view reason, // The obsolete reason-phrase
int version, // The HTTP-version
error_code& ec); // The error returned to the caller, if any
/// Called after receiving a header field.
void
on_field(
string_view name, // The field name
string_view value, // The field value
error_code& ec); // The error returned to the caller, if any
/// Called after the complete header is received.
void
on_header(
error_code& ec); // The error returned to the caller, if any
/// Called just before processing the body, if a body exists.
void
on_body(boost::optional<
std::uint64_t> const&
content_length, // Content length if known, else `boost::none`
error_code& ec); // The error returned to the caller, if any
/// Called for each piece of the body, if a body exists.
//
// If present, the chunked Transfer-Encoding will be removed
// before this callback is invoked.
//
void
on_data(
string_view s, // A portion of the body
error_code& ec); // The error returned to the caller, if any
/// Called for each chunk header.
void
on_chunk(
std::uint64_t size, // The size of the upcoming chunk
string_view extension, // The chunk-extension (may be empty)
error_code& ec); // The error returned to the caller, if any
/// Called when the complete message is parsed.
void
on_complete(error_code& ec);
public:
custom_parser() = default;
};
```
[endsect]

View File

@@ -26,20 +26,20 @@ The meaning of the nested types is as follows
declared with this [*Body] will have those operations defined.
]
][
[`body_writer`]
[`reader`]
[
An optional nested type meeting the requirements of
[link beast.ref.BodyReader [*BodyReader]]. If present, this defines
the algorithm used to obtain buffers representing a body of this type.
]
][
[`writer`]
[
An optional nested type meeting the requirements of
[link beast.ref.BodyWriter [*BodyWriter]]. If present, this defines the
algorithm used to transfer parsed octets into buffers representing the
body.
]
][
[`body_reader`]
[
An optional nested type meeting the requirements of
[link beast.ref.BodyReader [*BodyReader]]. If present, this defines
the algorithm used to obtain buffers representing a body of this type.
]
]
]

View File

@@ -29,95 +29,6 @@ namespace http {
state. It will handle chunked encoding and it understands
the semantics of the Connection, Content-Length, and Upgrade
fields.
The interface uses CRTP (Curiously Recurring Template Pattern).
To use this class, derive from @ref basic_parser. When bytes
are presented, the implementation will make a series of zero
or more calls to derived class members functions (referred to
as "callbacks" from here on) matching a specific signature.
Every callback must be provided by the derived class, or else
a compilation error will be generated. This exemplar shows
the signature and description of the callbacks required in
the derived class.
@par Derived Example
@code
template<bool isRequest>
struct derived
: basic_parser<isRequest, derived<isRequest>>
{
// When isRequest == true, called
// after the Request Line is received.
//
void
on_request(
string_view method,
string_view target,
int version,
error_code& ec);
// When isRequest == false, called
// after the Status Line is received.
//
void
on_response(
int status,
string_view reason,
int version,
error_code& ec);
// Called after receiving a field/value pair.
//
void
on_field(
string_view name,
string_view value,
error_code& ec);
// Called after the header is complete.
//
void
on_header(
error_code& ec);
// Called once before the body, if any, is started.
//
void
on_body(
boost::optional<std::uint64_t> content_length,
error_code& ec);
// Called zero or more times to provide body data.
//
void
on_data(
string_view s,
error_code& ec);
// 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
// chunk.
//
void
on_chunk(
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.
// This will be called even if there is no body.
//
void
on_complete(error_code& ec);
};
@endcode
If a callback sets the error code, the error will be propagated
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
@ref beast::flat_buffer class is provided, which guarantees
@@ -130,6 +41,88 @@ namespace http {
the structured portion of the HTTP message (header or chunk header)
is contained in a linear buffer.
The interface uses CRTP (Curiously Recurring Template Pattern).
To use this class directly, derive from @ref basic_parser. When
bytes are presented, the implementation will make a series of zero
or more calls to derived class members functions (termed "callbacks"
in this context) matching a specific signature.
Every callback must be provided by the derived class, or else
a compilation error will be generated. This exemplar shows
the signature and description of the callbacks required in
the derived class. If a callback sets the error code, the error
will be propagated to the caller of the parser.
@par Example
@code
template<bool isRequest>
class custom_parser
: public basic_parser<isRequest, custom_parser<isRequest>>
{
friend class basic_parser<isRequest, custom_parser>;
/// Called after receiving the request-line (isRequest == true).
void
on_request(
string_view method, // The method
string_view target, // The request-target
int version, // The HTTP-version
error_code& ec); // The error returned to the caller, if any
/// Called after receiving the start-line (isRequest == false).
void
on_response(
int status, // The status-code
string_view reason, // The obsolete reason-phrase
int version, // The HTTP-version
error_code& ec); // The error returned to the caller, if any
/// Called after receiving a header field.
void
on_field(
string_view name, // The field name
string_view value, // The field value
error_code& ec); // The error returned to the caller, if any
/// Called after the complete header is received.
void
on_header(
error_code& ec); // The error returned to the caller, if any
/// Called just before processing the body, if a body exists.
void
on_body(boost::optional<
std::uint64_t> const&
content_length, // Content length if known, else `boost::none`
error_code& ec); // The error returned to the caller, if any
/// Called for each piece of the body, if a body exists.
//
// If present, the chunked Transfer-Encoding will be removed
// before this callback is invoked.
//
void
on_data(
string_view s, // A portion of the body
error_code& ec); // The error returned to the caller, if any
/// Called for each chunk header.
void
on_chunk(
std::uint64_t size, // The size of the upcoming chunk
string_view extension, // The chunk-extension (may be empty)
error_code& ec); // The error returned to the caller, if any
/// Called when the complete message is parsed.
void
on_complete(error_code& ec);
public:
custom_parser() = default;
};
@endcode
@tparam isRequest A `bool` indicating whether the parser will be
presented with request or response message.
@@ -319,16 +312,19 @@ public:
/** 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:
Normally the parser returns after successfully parsing a structured
element (header, chunk header, or chunk body) even if there are octets
remaining in the input. This is necessary when attempting to parse the
header first, or when the caller wants to inspect information which may
be invalidated by subsequent parsing, such as a chunk extension. The
`eager` option controls whether the parser keeps going after parsing
structured element if there are octets remaining in the buffer and no
error occurs. This option is automatically set or cleared during certain
stream operations to improve performance with no change in functionality.
@li Immediately after the header
The default setting is `false`.
@li Immediately after any chunk header
The default is to stop after the header or any chunk header.
@param v `true` to set the eager parse option or `false` to disable it.
*/
void
eager(bool v)
@@ -339,25 +335,25 @@ public:
f_ &= ~flagEager;
}
/// Returns `true` if the parser will ignore the message body.
/// Returns `true` if the skip parse option is set.
bool
skip()
{
return (f_ & flagSkipBody) != 0;
}
/** Set the skip body option.
/** Set the skip parse 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.
This 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 or a chunked Transfer-Encoding. Depending on the request,
some responses do not carry a body. For example, a 200 response to a
CONNECT request from a tunneling proxy, or a response to a HEAD request.
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.
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.
@param v `true` to set the skip body option or `false` to disable it.
@note This function must called before any bytes are processed.
*/

View File

@@ -227,10 +227,8 @@ class parser
using base_type = basic_parser<isRequest,
parser<isRequest, Body, Fields>>;
using writer_type = typename Body::writer;
message<isRequest, Body, Fields> m_;
boost::optional<writer_type> wr_;
boost::optional<typename Body::writer> wr_;
public:
/// The type of message returned by the parser
@@ -329,8 +327,7 @@ public:
}
private:
friend class basic_parser<
isRequest, parser>;
friend class basic_parser<isRequest, parser>;
void
on_request(

View File

@@ -17,35 +17,30 @@
namespace beast {
namespace http {
/** Read some HTTP/1 message data from a stream.
/** Read part of a message from a stream using a parser.
This function synchronously advances the state of the
parser using the provided dynamic buffer and reading
from the input stream as needed. The call will block
until one of the following conditions is true:
This function is used to read part of a message from a stream into a
subclass of @ref basic_parser.
The call will block until one of the following conditions is true:
@li When expecting a message header, and the complete
header is received.
@li A call to @ref basic_parser::put with a non-empty buffer sequence
is successful.
@li When expecting a chunk header, and the complete
chunk header is received.
@li An error occurs.
@li When expecting body octets, one or more body octets
are received.
This operation is implemented in terms of one or
more calls to the stream's `read_some` function.
The implementation may read additional octets that lie past the
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
@li An error occurs in the stream or parser.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
This function is implemented in terms of one or more calls
to the stream's `read_some` function. The implementation may
read additional octets that lie past the end of the object
being parsed. This additional data is stored in the dynamic
buffer, which may be used in subsequent calls.
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -57,9 +52,9 @@ namespace http {
@param parser The parser to use.
@return The number of bytes processed from the dynamic
buffer. The caller should remove these bytes by calling
`consume` on the dynamic buffer.
@return The number of octets processed from the dynamic buffer.
The octets should be removed by calling `consume` on the dynamic
buffer after the read completes, regardless of any error.
@throws system_error Thrown on failure.
*/
@@ -73,34 +68,33 @@ read_some(
DynamicBuffer& buffer,
basic_parser<isRequest, Derived>& parser);
/** Read some HTTP/1 message data from a stream.
/** Read part of a message from a stream using a parser.
This function synchronously advances the state of the
parser using the provided dynamic buffer and reading
from the input stream as needed. The call will block
until one of the following conditions is true:
This function is used to read part of a message from a stream into a
subclass of @ref basic_parser.
The call will block until one of the following conditions is true:
@li When expecting a message header, and the complete
header is received.
@li A call to @ref basic_parser::put with a non-empty buffer sequence
is successful.
@li When expecting a chunk header, and the complete
chunk header is received.
@li An error occurs.
@li When expecting body octets, one or more body octets
are received.
This operation is implemented in terms of one or
more calls to the stream's `read_some` function.
The implementation may read additional octets that lie past the
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
@li An error occurs in the stream or parser.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
This function is implemented in terms of one or more calls
to the stream's `read_some` function. The implementation may
read additional octets that lie past the end of the object
being parsed. This additional data is stored in the dynamic
buffer, which may be used in subsequent calls.
@li @ref error::end_of_stream if no octets were parsed, or
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
@li @ref error::partial_message if any octets were parsed.
The function returns the number of bytes processed from the dynamic
buffer. The caller should remove these bytes by calling `consume` on
the dynamic buffer, regardless of any error.
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -115,9 +109,9 @@ read_some(
@param ec Set to the error, if any occurred.
@return The number of bytes processed from the dynamic
buffer. The caller should remove these bytes by calling
`consume` on the dynamic buffer.
@return The number of octets processed from the dynamic buffer.
The octets should be removed by calling `consume` on the dynamic
buffer after the read completes, regardless of any error.
*/
template<
class SyncReadStream,
@@ -130,24 +124,17 @@ read_some(
basic_parser<isRequest, Derived>& parser,
error_code& ec);
/** Start an asynchronous operation to read some HTTP/1 message data from a stream.
/** Read part of a message asynchronously from a stream using a parser.
This function asynchronously advances the state of the
parser using the provided dynamic buffer and reading from
the input stream as needed. The function call always
returns immediately. The asynchronous operation will
continue until one of the following conditions is true:
This function is used to asynchronously read part of a message from
a stream into a subclass of @ref basic_parser.
The function call always returns immediately. The asynchronous operation
will continue until one of the following conditions is true:
@li When expecting a message header, and the complete
header is received.
@li A call to @ref basic_parser::put with a non-empty buffer sequence
is successful.
@li When expecting a chunk header, and the complete
chunk header is received.
@li When expecting body octets, one or more body octets
are received.
@li An error occurs in the stream or parser.
@li An error occurs.
This operation is implemented in terms of zero or more calls to
the next layer's `async_read_some` function, and is known as a
@@ -157,14 +144,12 @@ read_some(
end of the object being parsed. This additional data is stored
in the stream buffer, which may be used in subsequent calls.
The completion handler will be called with the number of bytes
processed from the dynamic buffer. The caller should remove
these bytes by calling `consume` on the dynamic buffer.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b AsyncReadStream concept.
@@ -176,6 +161,8 @@ read_some(
first.
@param parser The parser to use.
The object must remain valid at least until the
handler is called; ownership is not transferred.
@param handler The handler to be called when the request
completes. Copies will be made of the handler as required.
@@ -188,6 +175,11 @@ read_some(
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using `boost::asio::io_service::post`.
The completion handler will receive as a parameter the number
of octets processed from the dynamic buffer. The octets should
be removed by calling `consume` on the dynamic buffer after
the read completes, regardless of any error.
*/
template<
class AsyncReadStream,
@@ -208,26 +200,28 @@ async_read_some(
//------------------------------------------------------------------------------
/** Read a header into an HTTP/1 parser from a stream.
/** Read a header from a stream using a parser.
This function synchronously reads from a stream and passes
data to the specified parser. The call will block until one
of the following conditions is true:
This function is used to read a header from a stream into a subclass
of @ref basic_parser.
The call will block until one of the following conditions is true:
@li The parser indicates that the complete header is received
@li @ref basic_parser::is_header_done returns `true`
@li An error occurs in the stream or parser.
@li An error occurs.
This function is implemented in terms of one or more calls
to the stream's `read_some` function. The implementation may
read additional octets that lie past the end of the object
being parsed. This additional data is stored in the dynamic
buffer, which may be used in subsequent calls.
This operation is implemented in terms of one or
more calls to the stream's `read_some` function.
The implementation may read additional octets that lie past the
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -255,26 +249,28 @@ read_header(
DynamicBuffer& buffer,
basic_parser<isRequest, Derived>& parser);
/** Read a header into an HTTP/1 parser from a stream.
/** Read a header from a stream using a parser.
This function synchronously reads from a stream and passes
data to the specified parser. The call will block until one
of the following conditions is true:
This function is used to read a header from a stream into a subclass
of @ref basic_parser.
The call will block until one of the following conditions is true:
@li The parser indicates that the complete header is received
@li @ref basic_parser::is_header_done returns `true`
@li An error occurs in the stream or parser.
@li An error occurs.
This function is implemented in terms of one or more calls
to the stream's `read_some` function. The implementation may
read additional octets that lie past the end of the object
being parsed. This additional data is stored in the dynamic
buffer, which may be used in subsequent calls.
This operation is implemented in terms of one or
more calls to the stream's `read_some` function.
The implementation may read additional octets that lie past the
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -303,29 +299,31 @@ read_header(
basic_parser<isRequest, Derived>& parser,
error_code& ec);
/** Read a header into an HTTP/1 parser asynchronously from a stream.
/** Read a header from a stream asynchronously using a parser.
This function is used to asynchronously read from a stream and
pass the data to the specified parser. The function call always
returns immediately. The asynchronous operation will continue
until one of the following conditions is true:
This function is used to asynchronously read a header from a stream
into a subclass of @ref basic_parser.
The function call always returns immediately. The asynchronous operation
will continue until one of the following conditions is true:
@li The parser indicates that the complete header is received
@li @ref basic_parser::is_header_done returns `true`
@li An error occurs in the stream or parser.
@li An error occurs.
This operation is implemented in terms of one or more calls to
the next layer's `async_read_some` function, and is known as a
the stream's `async_read_some` function, and is known as a
<em>composed operation</em>. The program must ensure that the
stream performs no other operations until this operation completes.
The implementation may read additional octets that lie past the
end of the object being parsed. This additional data is stored
in the stream buffer, which may be used in subsequent calls.
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b AsyncReadStream concept.
@@ -337,6 +335,8 @@ read_header(
first.
@param parser The parser to use.
The object must remain valid at least until the
handler is called; ownership is not transferred.
@param handler The handler to be called when the request
completes. Copies will be made of the handler as required.
@@ -371,26 +371,28 @@ async_read_header(
//------------------------------------------------------------------------------
/** Read into an HTTP/1 parser from a stream.
/** Read a complete message from a stream using a parser.
This function synchronously reads from a stream and passes
data to the specified parser. The call will block until one
of the following conditions is true:
This function is used to read a complete message from a stream into a
subclass of @ref basic_parser.
The call will block until one of the following conditions is true:
@li The parser indicates no more additional data is needed.
@li @ref basic_parser::is_done returns `true`
@li An error occurs in the stream or parser.
@li An error occurs.
This function is implemented in terms of one or more calls
to the stream's `read_some` function. The implementation may
read additional octets that lie past the end of the object
being parsed. This additional data is stored in the dynamic
buffer, which may be used in subsequent calls.
This operation is implemented in terms of one or
more calls to the stream's `read_some` function.
The implementation may read additional octets that lie past the
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -418,26 +420,28 @@ read(
DynamicBuffer& buffer,
basic_parser<isRequest, Derived>& parser);
/** Read into an HTTP/1 parser from a stream.
/** Read a complete message from a stream using a parser.
This function synchronously reads from a stream and passes
data to the specified parser. The call will block until one
of the following conditions is true:
This function is used to read a complete message from a stream into a
subclass of @ref basic_parser.
The call will block until one of the following conditions is true:
@li The parser indicates that no more data is needed.
@li @ref basic_parser::is_done returns `true`
@li An error occurs in the stream or parser.
@li An error occurs.
This function is implemented in terms of one or more calls
to the stream's `read_some` function. The implementation may
read additional octets that lie past the end of the object
being parsed. This additional data is stored in the dynamic
buffer, which may be used in subsequent calls.
This operation is implemented in terms of one or
more calls to the stream's `read_some` function.
The implementation may read additional octets that lie past the
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -466,29 +470,31 @@ read(
basic_parser<isRequest, Derived>& parser,
error_code& ec);
/** Read into an HTTP/1 parser asynchronously from a stream.
/** Read a complete message from a stream asynchronously using a parser.
This function is used to asynchronously read from a stream and
pass the data to the specified parser. The function call always
returns immediately. The asynchronous operation will continue
until one of the following conditions is true:
This function is used to asynchronously read a complete message from a
stream into a subclass of @ref basic_parser.
The function call always returns immediately. The asynchronous operation
will continue until one of the following conditions is true:
@li The parser indicates that no more data is needed.
@li @ref basic_parser::is_done returns `true`
@li An error occurs in the stream or parser.
@li An error occurs.
This operation is implemented in terms of one or more calls to
the next layer's `async_read_some` function, and is known as a
the stream's `async_read_some` function, and is known as a
<em>composed operation</em>. The program must ensure that the
stream performs no other operations until this operation completes.
The implementation may read additional octets that lie past the
end of the object being parsed. This additional data is stored
in the stream buffer, which may be used in subsequent calls.
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b AsyncReadStream concept.
@@ -500,6 +506,8 @@ read(
first.
@param parser The parser to use.
The object must remain valid at least until the
handler is called; ownership is not transferred.
@param handler The handler to be called when the request
completes. Copies will be made of the handler as required.
@@ -534,26 +542,27 @@ async_read(
//------------------------------------------------------------------------------
/** Read an HTTP/1 message from a stream.
/** Read a complete message from a stream.
This function is used to synchronously read a message from
a stream. The call blocks until one of the following conditions
is true:
This function is used to read a complete message from a stream using HTTP/1.
The call will block until one of the following conditions is true:
@li A complete message is read in.
@li The entire message is read.
@li An error occurs in the stream or parser.
@li An error occurs.
This function is implemented in terms of one or more calls
to the stream's `read_some` function. The implementation may
read additional octets that lie past the end of the message
being parsed. This additional data is stored in the dynamic
buffer, which may be used in subsequent calls.
This operation is implemented in terms of one or
more calls to the stream's `read_some` function.
The implementation may read additional octets that lie past the
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -564,9 +573,8 @@ async_read(
dynamic buffer's input sequence will be given to the parser
first.
@param msg An object used to store the message. Any
contents will be overwritten. The type must support
copy assignment or move assignment.
@param msg An object used to store the message. Any contents will
be overwritten. The type must support copy or move assignment.
@throws system_error Thrown on failure.
*/
@@ -580,26 +588,27 @@ read(
DynamicBuffer& buffer,
message<isRequest, Body, Fields>& msg);
/** Read an HTTP/1 message from a stream.
/** Read a complete message from a stream.
This function is used to synchronously read a message from
a stream. The call blocks until one of the following conditions
is true:
This function is used to read a complete message from a stream using HTTP/1.
The call will block until one of the following conditions is true:
@li A complete message is read in.
@li The entire message is read.
@li An error occurs in the stream or parser.
@li An error occurs.
This function is implemented in terms of one or more calls
to the stream's `read_some` function. The implementation may
read additional octets that lie past the end of the message
being parsed. This additional data is stored in the dynamic
buffer, which may be used in subsequent calls.
This operation is implemented in terms of one or
more calls to the stream's `read_some` function.
The implementation may read additional octets that lie past the
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -610,9 +619,8 @@ read(
dynamic buffer's input sequence will be given to the parser
first.
@param msg An object used to store the message. Any
contents will be overwritten. The type must support
copy assignment or move assignment.
@param msg An object used to store the message. Any contents will
be overwritten. The type must support copy or move assignment.
@param ec Set to the error, if any occurred.
*/
@@ -627,31 +635,33 @@ read(
message<isRequest, Body, Fields>& msg,
error_code& ec);
/** Read an HTTP/1 message asynchronously from a stream.
/** Read a complete message from a stream asynchronously.
This function is used to asynchronously read a message from
a stream. The function call always returns immediately. The
asynchronous operation will continue until one of the following
conditions is true:
This function is used to asynchronously read a complete message from a
stream using HTTP/1.
The function call always returns immediately. The asynchronous operation
will continue until one of the following conditions is true:
@li A complete message is read in.
@li The entire message is read.
@li An error occurs in the stream or parser.
@li An error occurs.
This operation is implemented in terms of one or more calls to
the stream's `async_read_some` function, and is known as a
<em>composed operation</em>. The program must ensure that the
stream performs no other operations until this operation completes.
The implementation may read additional octets that lie past the
end of the message being parsed. This additional data is stored
in the dynamic buffer, which may be used in subsequent calls.
end of the message being read. This additional data is stored
in the dynamic buffer, which must be retained for subsequent reads.
If the end of the stream is reached during the read, the
value @ref error::partial_message is indicated as the
error if bytes have been processed, else the error
@ref error::end_of_stream is indicated.
If the stream returns the error `boost::asio::error::eof` indicating the
end of file during a read, the error returned from this function will be:
@param stream The stream to read the message from.
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@param stream The stream from which the data is to be read.
The type must support the @b AsyncReadStream concept.
@param buffer A @b DynamicBuffer holding additional bytes
@@ -660,10 +670,10 @@ read(
dynamic buffer's input sequence will be given to the parser
first.
@param msg An object used to store the header. Any contents
will be overwritten. The type must support copy assignment or
move assignment. The object must remain valid at least until
the completion handler is called; ownership is not transferred.
@param msg An object used to store the message. Any contents will
be overwritten. The type must support copy or move assignment.
The object must remain valid at least until the
handler is called; ownership is not transferred.
@param handler The handler to be called when the operation
completes. Copies will be made of the handler as required.

View File

@@ -131,6 +131,8 @@ write_some(SyncWriteStream& stream, serializer<
The type must support the @b AsyncWriteStream concept.
@param sr The serializer to use.
The object must remain valid at least until the
handler is called; ownership is not transferred.
@param handler The handler to be called when the operation
completes. Copies will be made of the handler as required.
@@ -244,6 +246,8 @@ write_header(SyncWriteStream& stream, serializer<
The type must support the @b AsyncWriteStream concept.
@param sr The serializer to use.
The object must remain valid at least until the
handler is called; ownership is not transferred.
@param handler The handler to be called when the operation
completes. Copies will be made of the handler as required.
@@ -354,6 +358,8 @@ write(SyncWriteStream& stream, serializer<
The type must support the @b AsyncWriteStream concept.
@param sr The serializer to use.
The object must remain valid at least until the
handler is called; ownership is not transferred.
@param handler The handler to be called when the operation
completes. Copies will be made of the handler as required.
@@ -465,8 +471,9 @@ write(SyncWriteStream& stream,
@param stream The stream to which the data is to be written.
The type must support the @b AsyncWriteStream concept.
@param msg The message to write. The object must remain valid at least
until the completion handler is called; ownership is not transferred.
@param msg The message to write.
The object must remain valid at least until the
handler is called; ownership is not transferred.
@param handler The handler to be called when the operation
completes. Copies will be made of the handler as required.

View File

@@ -21,6 +21,130 @@
namespace beast {
namespace http {
namespace design {
//--------------------------------------------------------------------------
//
// Example: Custom Parser
//
//--------------------------------------------------------------------------
template<bool isRequest>
class custom_parser
: public basic_parser<isRequest, custom_parser<isRequest>>
{
friend class basic_parser<isRequest, custom_parser>;
/// Called after receiving the request-line (isRequest == true).
void
on_request(
string_view method, // The method
string_view target, // The request-target
int version, // The HTTP-version
error_code& ec); // The error returned to the caller, if any
/// Called after receiving the start-line (isRequest == false).
void
on_response(
int status, // The status-code
string_view reason, // The obsolete reason-phrase
int version, // The HTTP-version
error_code& ec); // The error returned to the caller, if any
/// Called after receiving a header field.
void
on_field(
string_view name, // The field name
string_view value, // The field value
error_code& ec); // The error returned to the caller, if any
/// Called after the complete header is received.
void
on_header(
error_code& ec); // The error returned to the caller, if any
/// Called just before processing the body, if a body exists.
void
on_body(boost::optional<
std::uint64_t> const&
content_length, // Content length if known, else `boost::none`
error_code& ec); // The error returned to the caller, if any
/// Called for each piece of the body, if a body exists.
//
// If present, the chunked Transfer-Encoding will be removed
// before this callback is invoked.
//
void
on_data(
string_view s, // A portion of the body
error_code& ec); // The error returned to the caller, if any
/// Called for each chunk header.
void
on_chunk(
std::uint64_t size, // The size of the upcoming chunk
string_view extension, // The chunk-extension (may be empty)
error_code& ec); // The error returned to the caller, if any
/// Called when the complete message is parsed.
void
on_complete(error_code& ec);
public:
custom_parser() = default;
};
template<bool isRequest>
void custom_parser<isRequest>::
on_request(string_view method, string_view path, int version, error_code& ec)
{
}
template<bool isRequest>
void custom_parser<isRequest>::
on_response(int status, string_view reason, int version, error_code& ec)
{
}
template<bool isRequest>
void custom_parser<isRequest>::
on_field(string_view name, string_view value, error_code& ec)
{
}
template<bool isRequest>
void custom_parser<isRequest>::
on_header(error_code& ec)
{
}
template<bool isRequest>
void custom_parser<isRequest>::
on_body(boost::optional<std::uint64_t> const& content_length, error_code& ec)
{
}
template<bool isRequest>
void custom_parser<isRequest>::
on_data(string_view s, error_code& ec)
{
}
template<bool isRequest>
void custom_parser<isRequest>::
on_chunk(std::uint64_t size, string_view extension, error_code& ec)
{
}
template<bool isRequest>
void custom_parser<isRequest>::
on_complete(error_code& ec)
{
}
} // design
class design_test
: public beast::unit_test::suite
, public beast::test::enable_yield_to
@@ -618,6 +742,48 @@ public:
BEAST_EXPECTS(! ec, ec.message());
}
//--------------------------------------------------------------------------
//
// Example: Custom Parser
//
//--------------------------------------------------------------------------
void
doCustomParser()
{
{
string_view s{
"POST / HTTP/1.1\r\n"
"User-Agent: test\r\n"
"Content-Length: 13\r\n"
"\r\n"
"Hello, world!"
};
error_code ec;
design::custom_parser<true> p;
p.put(boost::asio::buffer(
s.data(), s.size()), ec);
BEAST_EXPECTS(! ec, ec.message());
}
{
string_view s{
"HTTP/1.1 200 OK\r\n"
"Server: test\r\n"
"Transfer-Encoding: chunked\r\n"
"\r\n"
"d\r\n"
"Hello, world!"
"\r\n"
"0\r\n\r\n"
};
error_code ec;
design::custom_parser<false> p;
p.put(boost::asio::buffer(
s.data(), s.size()), ec);
BEAST_EXPECTS(! ec, ec.message());
}
}
//--------------------------------------------------------------------------
//
// Deferred Body type commitment
@@ -788,6 +954,8 @@ public:
doCgiResponse();
doRelay();
doParseStdStream();
doCustomParser();
doDeferredBody();
}
};