forked from boostorg/beast
Documentation work
This commit is contained in:
1 parent
00667f3cf2
commit
78d9e3bbce
11 files changed
+665
-351
No files matched your search
+7
-3
@@ -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]
|
||||
|
||||
|
||||
@@ -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__.
|
||||
]]
|
||||
]
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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]
|
||||
@@ -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.
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
Reference in new issue
Block a user