Documentation work

This commit is contained in:
Vinnie Falco
2017-07-16 10:20:21 -07:00
parent 4e44ddbd45
commit 04887c49e0
16 changed files with 395 additions and 170 deletions

View File

@ -4,6 +4,7 @@ Version 83:
* Add buffer_front
* Add wstest compression option
* Turn some flat_static_buffer_tests on
* Documentation work
WebSocket

View File

@ -69,6 +69,124 @@ format using __Asio__. Specifically, the library provides:
]
]
Interfaces for operating on HTTP messages are structured into several
layers. The highest level provides ease of use, while lower levels provide
progressively more control, options, and flexibility. At the lowest level
customization points are provided, where user defined types can replace
parts of the implementation. The layers are arranged thusly:
[table
[[Level][Read/Write What][Description]]
[
[[*6]]
[
__message__
][
At the highest level, these free functions send or receive
a complete HTTP message in one call. They are designed for
ease of use:
[link beast.ref.beast__http__read.overload4 `read`],
[link beast.ref.beast__http__write.overload4 `write`],
[link beast.ref.beast__http__async_read.overload2 `async_read`], and
[link beast.ref.beast__http__async_write.overload2 `async_write`].
]
][
[[*5]]
[
__parser__, __serializer__
][
For more control, callers may take responsibility for managing the
required __parser__ or __serializer__ transient state objects.
This allows additional configuration such as limiting the number
of bytes for message components during parsing, or regulating the
size of buffers emitted during output. These functions send or
receive complete messages using a serializer or parser:
[link beast.ref.beast__http__read.overload2 `read`],
[link beast.ref.beast__http__write.overload2 `write`],
[link beast.ref.beast__http__async_read.overload1 `async_read`], and
[link beast.ref.beast__http__async_write.overload1 `async_write`].
]
][
[[*4]]
[
__header__
][
Sometimes it is necessary to first send or receive the HTTP
header. For example, to read the header and take action before
continuing to read the body. These functions use a __parser__
or __serializer__ to read or write the header:
[link beast.ref.beast__http__read_header.overload2 `read_header`],
[link beast.ref.beast__http__write_header.overload2 `write_header`],
[link beast.ref.beast__http__async_read_header `async_read_header`], and
[link beast.ref.beast__http__async_write_header `async_write_header`].
]
][
[[*3]]
[
partial __message__
][
All of the stream operations at higher levels thus far have operated
on a complete header or message. At this level it is possible to
send and receive messages incrementally. This allows resource
constrained implementations to perform work bounded on storage,
or allows better control when setting timeouts for example.
These functions read or write bounded amounts of data and return
the number of bytes transacted:
[link beast.ref.beast__http__read_some.overload2 `read_some`],
[link beast.ref.beast__http__write_some.overload2 `write_some`],
[link beast.ref.beast__http__async_read_some `async_read_some`], and
[link beast.ref.beast__http__async_write_some `async_write_some`].
]
][
[[*2]]
[
[@https://tools.ietf.org/html/rfc7230#section-4.1 ['chunked-body]]
][
Until now parse and serialize operations apply or remove the chunked
transfer coding as needed for message payloads whose size is not known
ahead of time. For some domain specific niches, it is necessary
to assume direct control over incoming or outgoing chunks in a chunk
encoded message payload.
For parsing this is achieved by setting hooks using the functions
[link beast.ref.beast__http__parser.on_chunk_header `on_chunk_header`] and/or
[link beast.ref.beast__http__parser.on_chunk_body `on_chunk_body`].
For serializing callers may first emit the header, and then use
these buffer sequence adapters to control the contents of each chunk
including
[@https://tools.ietf.org/html/rfc7230#section-4.1.1 ['chunk extensions]]
and the
[@https://tools.ietf.org/html/rfc7230#section-4.1.2 ['trailer-part]]:
[link beast.ref.beast__http__chunk_body `chunk_body`],
[link beast.ref.beast__http__chunk_crlf `chunk_crlf`],
[link beast.ref.beast__http__chunk_header `chunk_header`], and
[link beast.ref.beast__http__chunk_last `chunk_last`].
]
][
[[*1]]
[
buffers
][
For ultimate control, the use of library stream algorithms may
be bypassed entirely and instead work directly with buffers by
calling members of __parser__ or __serializer__.
]
][
[[*0]]
[
['user-defined]
][
In addition to the typical customization points of __Stream__
and __DynamicBuffer__, user-defined types may replace parts of
the library implementation at the lowest level. The customization
points include __Fields__ for creating a container to store HTTP
fields, __Body__ for defining containers and algorithms used for
HTTP message payloads, and user-defined subclasses of
__basic_parser__ for implementing custom message representation
strategies.
]
]]
[note
This documentation assumes some familiarity with __Asio__ and
the HTTP protocol specification described in __rfc7230__. Sample

View File

@ -11,17 +11,24 @@ A [*Body] type is supplied as a template argument to the __message__ class. It
controls both the type of the data member of the resulting message object, and
the algorithms used during parsing and serialization.
[heading Associated Types]
* [link beast.ref.beast__http__is_body `is_body`]
* __BodyReader__
* __BodyWriter__
[heading Requirements]
In this table:
* `X` is a type meeting the requirements of [*Body].
* `m` is a value of type `message<b, X, F>` where `b` is a `bool` value
* `B` is a type meeting the requirements of [*Body].
* `m` is a value of type `message<b, B, F>` where `b` is a `bool` value
and `F` is a type meeting the requirements of [*Fields].
[table Body requirements
[[expression] [type] [semantics, pre/post-conditions]]
[table Valid expressions
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
[
[`X::value_type`]
[`B::value_type`]
[]
[
The type of the `message::body` member.
@ -29,7 +36,7 @@ In this table:
will be not movable or not copyable.
]
][
[`X::writer`]
[`B::writer`]
[]
[
If present, indicates that the body can hold a message body
@ -39,7 +46,7 @@ In this table:
are placed.
]
][
[`X::reader`]
[`B::reader`]
[]
[
If present, indicates that the body is serializable. The type
@ -48,11 +55,16 @@ In this table:
the message body for serialization.
]
][
[`X::size(X::value_type v)`]
[
```
B::size(
B::value_type body)
```
]
[`std::uint64_t`]
[
This static member function is optional. It returns the payload
size of `v` not including any chunked transfer encoding. The
size of `body` not including any chunked transfer encoding. The
function shall not exit via an exception.
When this function is present:
@ -80,15 +92,7 @@ In this table:
will erase the Content-Length field, and add "chunked" as the last
encoding in the Transfer-Encoding field if it is not already present.
]
][
[`is_body<X>`]
[`std::true_type`]
[
An alias for `std::true_type` for `X`, otherwise an alias
for `std::false_type`.
]
]
]
]]
[heading Exemplar]
@ -97,9 +101,11 @@ In this table:
[heading Models]
* [link beast.ref.beast__http__basic_dynamic_body `basic_dynamic_body`]
* [link beast.ref.beast__http__basic_file_body `basic_file_body`]
* [link beast.ref.beast__http__basic_string_body `basic_string_body`]
* [link beast.ref.beast__http__buffer_body `buffer_body`]
* [link beast.ref.beast__http__dynamic_body `dynamic_body`]
* [link beast.ref.beast__http__empty_body `empty_body`]
* [link beast.ref.beast__http__string_body `string_body`]
* [link beast.ref.beast__http__span_body `span_body`]
* [link beast.ref.beast__http__vector_body `vector_body`]
[endsect]

View File

@ -20,44 +20,39 @@ intended to obtain buffers for these scenarios:
* Body data generated dynamically from other threads.
* Body data computed algorithmically.
In this table:
* `X` denotes a type meeting the requirements of [*BodyReader].
* `B` denotes a __Body__ where
`std::is_same<X, B::reader>::value == true`.
* `a` denotes a value of type `X`.
* `m` denotes a possibly const value of type `message&` where
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
* `ec` is a value of type [link beast.ref.beast__error_code `error_code&`].
* `R<T>` is the type `boost::optional<std::pair<T, bool>>`.
[heading Associated Types]
* [link beast.ref.beast__http__is_body_reader `is_body_reader`]
* __Body__
* [link beast.ref.beast__http__is_body_reader `is_body_reader`]
[heading Requirements]
[heading BodyReader requirements]
[table Valid Expressions
In this table:
* `R` denotes a type meeting the requirements of [*BodyReader].
* `B` denotes a __Body__ where
`std::is_same<R, B::reader>::value == true`.
* `a` denotes a value of type `R`.
* `m` denotes a possibly const value of type `message&` where
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
* `ec` is a value of type [link beast.ref.beast__error_code `error_code&`].
* `R<T>` is the type `boost::optional<std::pair<T, bool>>`.
[table Valid expressions
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
[
[`X::const_buffers_type`]
[`R::const_buffers_type`]
[]
[
A type which meets the requirements of __ConstBufferSequence__.
This is the type of buffer returned by `X::get`.
This is the type of buffer returned by `R::get`.
]
][
[`X(m);`]
[`R(m);`]
[]
[
Constructible from `m`. The lifetime of `m` is guaranteed
to end no earlier than after the `X` is destroyed.
to end no earlier than after the `R` is destroyed.
The reader shall not access the contents of `m` before the
first call to `init`, permitting lazy construction of the
message.
@ -65,11 +60,11 @@ In this table:
The constructor may optionally require that `m` is const, which
has these consequences:
* If `X` requires that `m` is a const reference, then serializers
* If `R` requires that `m` is a const reference, then serializers
constructed for messages with this body type will also require a
const reference to a message, otherwise:
* If `X` requires that `m` is a non-const reference, then serializers
* If `R` requires that `m` is a non-const reference, then serializers
constructed for messages with this body type will aso require
a non-const reference to a message.
]
@ -85,7 +80,7 @@ In this table:
]
][
[`a.get(ec)`]
[`R<X::const_buffers_type>`]
[`R<R::const_buffers_type>`]
[
Called one or more times after `init` succeeds. This function
returns `boost::none` if all buffers representing the body have
@ -100,8 +95,7 @@ In this table:
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if there was one.
]
]
]
]]
[heading Exemplar]
@ -112,6 +106,9 @@ In this table:
* [link beast.ref.beast__http__basic_dynamic_body.reader `basic_dynamic_body::reader`]
* [link beast.ref.beast__http__basic_file_body__reader `basic_file_body::reader`]
* [link beast.ref.beast__http__basic_string_body.reader `basic_string_body::reader`]
* [link beast.ref.beast__http__buffer_body.reader `buffer_body::reader`]
* [link beast.ref.beast__http__empty_body.reader `empty_body::reader`]
* [link beast.ref.beast__http__span_body.reader `span_body::reader`]
* [link beast.ref.beast__http__vector_body.reader `vector_body::reader`]
[endsect]

View File

@ -20,37 +20,33 @@ representation:
to compress it first.
* Saving body data to a file
In this table:
* `X` denotes a type meeting the requirements of [*BodyWriter].
* `B` denotes a __Body__ where
`std::is_same<X, B::writer>::value == true`.
* `a` denotes a value of type `X`.
* `b` is an object whose type meets the requirements of __ConstBufferSequence__
* `m` denotes a value of type `message&` where
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
* `n` is a value of type `boost::optional<std::uint64_t>`.
* `ec` is a value of type [link beast.ref.beast__error_code `error_code&`].
[heading Associated Types]
* __Body__
* [link beast.ref.beast__http__is_body_writer `is_body_writer`]
* __Body__
[table Writer requirements
[[expression] [type] [semantics, pre/post-conditions]]
[heading Requirements]
In this table:
* `W` denotes a type meeting the requirements of [*BodyWriter].
* `B` denotes a __Body__ where
`std::is_same<W, B::writer>::value == true`.
* `a` denotes a value of type `W`.
* `b` is an object whose type meets the requirements of __ConstBufferSequence__
* `m` denotes a value of type `message&` where
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
* `n` is a value of type `boost::optional<std::uint64_t>`.
* `ec` is a value of type [link beast.ref.beast__error_code `error_code&`].
[table Valid expressions
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
[
[`X(m);`]
[`W(m);`]
[]
[
Constructible from `m`. The lifetime of `m` is guaranteed to
end no earlier than after the `X` is destroyed. The constructor
end no earlier than after the `W` is destroyed. The constructor
will be called after a complete header is stored in `m`, and
before parsing body octets for messages indicating that a body
is present The writer shall not access the contents of `m` before
@ -102,8 +98,7 @@ In this table:
An alias for `std::true_type` for `B`, otherwise an alias
for `std::false_type`.
]
]
]
]]
[heading Exemplar]
@ -112,8 +107,11 @@ In this table:
[heading Models]
* [link beast.ref.beast__http__basic_dynamic_body.writer `basic_dynamic_body::writer`]
* [link beast.ref.beast__http__basic_file_body__reader `basic_file_body::writer`]
* [link beast.ref.beast__http__basic_file_body__writer `basic_file_body::writer`]
* [link beast.ref.beast__http__basic_string_body.writer `basic_string_body::writer`]
* [link beast.ref.beast__http__buffer_body.writer `buffer_body::writer`]
* [link beast.ref.beast__http__empty_body.writer `empty_body::writer`]
* [link beast.ref.beast__http__span_body.writer `span_body::writer`]
* [link beast.ref.beast__http__vector_body.writer `vector_body::writer`]
[endsect]

View File

@ -31,65 +31,65 @@ implementation strategies:
size of the character sequence. This is the implementation approach
currently offered by __multi_buffer__.
In this table:
[heading Associated Types]
* `X` denotes a dynamic buffer class.
* `a` denotes a value of type `X`.
* `c` denotes a (possibly const) value of type `X`.
* [link beast.ref.beast__is_dynamic_buffer `is_dynamic_buffer`]
* __ConstBufferSequence__
* __MutableBufferSequence__
[heading Requirements]
* `D` denotes a dynamic buffer class.
* `a` denotes a value of type `D`.
* `c` denotes a (possibly const) value of type `D`.
* `n` denotes a value of type `std::size_t`.
* `T` denotes a type meeting the requirements for __ConstBufferSequence__.
* `U` denotes a type meeting the requirements for __MutableBufferSequence__.
[table DynamicBuffer requirements
[[expression] [type] [semantics, pre/post-conditions]]
[table Valid expressions
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
[
[`X::const_buffers_type`]
[`D::const_buffers_type`]
[`T`]
[
This type represents the memory associated with the input sequence.
]
]
[
[`X::mutable_buffers_type`]
][
[`D::mutable_buffers_type`]
[`U`]
[
This type represents the memory associated with the output sequence.
]
]
[
][
[`c.size()`]
[`std::size_t`]
[
Returns the size, in bytes, of the input sequence.
]
]
[
][
[`c.max_size()`]
[`std::size_t`]
[
Returns the permitted maximum of the sum of the sizes of the input
sequence and output sequence.
]
]
[
][
[`c.capacity()`]
[`std::size_t`]
[
Returns the maximum sum of the sizes of the input sequence and output
sequence that the dynamic buffer can hold without requiring reallocation.
]
]
[
][
[`c.data()`]
[`X::const_buffers_type`]
[`D::const_buffers_type`]
[
Returns a constant buffer sequence u that represents the memory
associated with the input sequence, and where `buffer_size(u) == size()`.
]
]
[
][
[`a.prepare(n)`]
[`X::mutable_buffers_type`]
[`D::mutable_buffers_type`]
[
Returns a mutable buffer sequence u representing the output sequence,
and where `buffer_size(u) == n`. The dynamic buffer reallocates memory
@ -98,8 +98,7 @@ In this table:
Throws: `length_error` if `size() + n` exceeds `max_size()`.
]
]
[
][
[`a.commit(n)`]
[ ]
[
@ -110,8 +109,7 @@ In this table:
mutable buffer sequences previously obtained using `data()` or
`prepare()` are invalidated.
]
]
[
][
[`a.consume(n)`]
[ ]
[
@ -120,8 +118,7 @@ In this table:
is removed. All constant or mutable buffer sequences previously
obtained using `data()` or `prepare()` are invalidated.
]
]
]
]]
[heading Models]
@ -131,6 +128,8 @@ In this table:
* [link beast.ref.beast__flat_buffer `flat_buffer`]
* [link beast.ref.beast__flat_static_buffer `flat_static_buffer`]
* [link beast.ref.beast__flat_static_buffer_base `flat_static_buffer_base`]
* [link beast.ref.beast__static_buffer `static_buffer`]
* [link beast.ref.beast__static_buffer_base `static_buffer_base`]
* [link beast.ref.beast__multi_buffer `multi_buffer`]
[endsect]

View File

@ -15,28 +15,20 @@ be serialized.
[heading Associated Types]
* __FieldsReader__
* [link beast.ref.beast__http__is_fields `is_fields`]
* __FieldsReader__
[heading Requirements]
In this table:
* `F` denotes a type that meets the requirements of [*Fields].
* `R` denotes a type meeting the requirements of __FieldsReader__.
* `a` denotes a value of type `F`.
* `c` denotes a (possibly const) value of type `F`.
* `b` is a value of type `bool`
* `n` is a value of type `boost::optional<std::uint64_t>`.
* `s` is a value of type [link beast.ref.beast__string_view `string_view`].
* `v` is a value of type `unsigned int` representing the HTTP-version.
[table Valid expressions

View File

@ -20,51 +20,45 @@ calls into it once to retrieve the buffers.
In this table:
* `X` denotes a type that meets the requirements of [*FieldsReader].
* `R` denotes a type that meets the requirements of [*FieldsReader].
* `F` denotes a __Fields__ where
`std::is_same<X, F::reader>::value == true`.
* `a` is a value of type `X`.
`std::is_same<R, F::reader>::value == true`.
* `a` is a value of type `R`.
* `f` is a value of type `F`.
* `v` is an `unsigned` value representing the HTTP version.
* `c` is an `unsigned` representing the HTTP status-code.
* `m` is a value of type [link beast.ref.beast__http__verb `verb`].
[table Valid expressions
[[expression][type][semantics, pre/post-conditions]]
[
[`X::const_buffers_type`]
[`R::const_buffers_type`]
[]
[
A type which meets the requirements of __ConstBufferSequence__.
This is the type of buffer returned by `X::get`.
This is the type of buffer returned by `R::get`.
]
][
[`X(f,v,m)`]
[`R(f,v,m)`]
[]
[
The implementation calls this constructor to indicate
that the fields being serialized form part of an HTTP
request. The lifetime of `f` is guaranteed
to end no earlier than after the `X` is destroyed.
to end no earlier than after the `R` is destroyed.
]
][
[`X(f,v,c)`]
[`R(f,v,c)`]
[]
[
The implementation calls this constructor to indicate
that the fields being serialized form part of an HTTP
response. The lifetime of `f` is guaranteed
to end no earlier than after the `X` is destroyed.
to end no earlier than after the `R` is destroyed.
]
][
[`a.get()`]
[`X::const_buffers_type`]
[`R::const_buffers_type`]
[
Called once after construction, this function returns
a constant buffer sequence containing the serialized

View File

@ -11,6 +11,13 @@ The [*File] concept abstracts access to files in the underlying file system.
To support other platform interfaces, users may author their own [*File]
types which meet these requirements.
[heading Associated Types]
* [link beast.ref.beast__file_mode `file_mode`]
* [link beast.ref.beast__is_file `is_file`]
[heading Requirements]
In this table:
* `F` is a [*File] type
@ -24,13 +31,8 @@ In this table:
* `c` is any possibly-const pointer to memory
* `ec` is a reference of type [link beast.ref.beast__error_code `error_code`]
[heading Associated Types]
* [link beast.ref.beast__file_mode `file_mode`]
* [link beast.ref.beast__is_file `is_file`]
[heading File Requirements]
[table Valid Expressions
[table Valid expressions
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
[[Operation] [Return Type] [Semantics, Pre/Post-conditions]]
[
[`F()`]
@ -168,6 +170,8 @@ In this table:
[heading Models]
* [link beast.ref.beast__file_posix `file_posix`]
* [link beast.ref.beast__file_stdio `file_stdio`]
* [link beast.ref.beast__file_win32 `file_win32`]
[endsect]

View File

@ -181,19 +181,16 @@
<member><link linkend="beast.ref.beast__buffers_adapter">buffers_adapter</link></member>
<member><link linkend="beast.ref.beast__consuming_buffers">consuming_buffers</link></member>
<member><link linkend="beast.ref.beast__drain_buffer">drain_buffer</link></member>
<member><link linkend="beast.ref.beast__error_category">error_category</link></member>
<member><link linkend="beast.ref.beast__error_code">error_code</link></member>
<member><link linkend="beast.ref.beast__error_condition">error_condition</link></member>
<member><link linkend="beast.ref.beast__file">file</link></member>
<member><link linkend="beast.ref.beast__file_mode">file_mode</link></member>
<member><link linkend="beast.ref.beast__file_posix">file_posix</link></member>
<member><link linkend="beast.ref.beast__file_stdio">file_stdio</link></member>
<member><link linkend="beast.ref.beast__file_win32">file_win32</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">&nbsp;</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.beast__file_win32">file_win32</link></member>
<member><link linkend="beast.ref.beast__flat_buffer">flat_buffer</link></member>
<member><link linkend="beast.ref.beast__flat_static_buffer">flat_static_buffer</link></member>
<member><link linkend="beast.ref.beast__flat_static_buffer_base">flat_static_buffer_base</link></member>
@ -209,7 +206,6 @@
<member><link linkend="beast.ref.beast__static_string">static_string</link></member>
<member><link linkend="beast.ref.beast__string_param">string_param</link></member>
<member><link linkend="beast.ref.beast__string_view">string_view</link></member>
<member><link linkend="beast.ref.beast__system_error">system_error</link></member>
</simplelist>
</entry>
<entry valign="top">
@ -225,12 +221,10 @@
<member><link linkend="beast.ref.beast__ostream">ostream</link></member>
<member><link linkend="beast.ref.beast__read_size">read_size</link></member>
<member><link linkend="beast.ref.beast__read_size_or_throw">read_size_or_throw</link></member>
<member><link linkend="beast.ref.beast__system_category">system_category</link></member>
<member><link linkend="beast.ref.beast__to_static_string">to_static_string</link></member>
</simplelist>
<bridgehead renderas="sect3">Constants</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.beast__errc">errc</link></member>
<member><link linkend="beast.ref.beast__file_mode">file_mode</link></member>
</simplelist>
</entry>
@ -253,6 +247,15 @@
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Aliases</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.beast__errc">errc</link></member>
<member><link linkend="beast.ref.beast__error_category">error_category</link></member>
<member><link linkend="beast.ref.beast__error_code">error_code</link></member>
<member><link linkend="beast.ref.beast__error_condition">error_condition</link></member>
<member><link linkend="beast.ref.beast__system_category">system_category</link></member>
<member><link linkend="beast.ref.beast__system_error">system_error</link></member>
</simplelist>
<bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.concepts.streams.AsyncStream">AsyncStream</link></member>
@ -284,6 +287,7 @@
</row>
</tbody>
</tgroup>
<!--
<tgroup cols="1">
<colspec colname="a"/>
<thead>
@ -304,4 +308,5 @@
</row>
</tbody>
</tgroup>
-->
</informaltable>

View File

@ -107,8 +107,7 @@ INPUT = \
../include/beast/core \
../include/beast/http \
../include/beast/websocket \
../include/beast/zlib \
../extras/beast/doc_debug.hpp
../include/beast/zlib
INPUT_ENCODING = UTF-8
FILE_PATTERNS =

View File

@ -873,6 +873,7 @@ template<bool isRequest>
class custom_parser
: public basic_parser<isRequest, custom_parser<isRequest>>
{
private:
// The friend declaration is needed,
// otherwise the callbacks must be made public.
friend class basic_parser<isRequest, custom_parser>;
@ -915,14 +916,14 @@ class custom_parser
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.
This is used when there is no chunked transfer coding.
The function returns the number of bytes consumed from the
input buffer. Any input octets not consumed will be will be
presented on subsequent calls.
*/
/// Called for each piece of the body, if a body exists.
//!
//! This is used when there is no chunked transfer coding.
//!
//! The function returns the number of bytes consumed from the
//! input buffer. Any input octets not consumed will be will be
//! presented on subsequent calls.
//!
std::size_t
on_body_impl(
string_view s, // A portion of the body
@ -936,16 +937,16 @@ class custom_parser
string_view extension, // The chunk extensions (may be empty)
error_code& ec); // The error returned to the caller, if any
/** Called to deliver the chunk body.
This is used when there is a chunked transfer coding. The
implementation will automatically remove the encoding before
calling this function.
The function returns the number of bytes consumed from the
input buffer. Any input octets not consumed will be will be
presented on subsequent calls.
*/
/// Called to deliver the chunk body.
//!
//! This is used when there is a chunked transfer coding. The
//! implementation will automatically remove the encoding before
//! calling this function.
//!
//! The function returns the number of bytes consumed from the
//! input buffer. Any input octets not consumed will be will be
//! presented on subsequent calls.
//!
std::size_t
on_chunk_body_impl(
std::uint64_t remain, // The number of bytes remaining in the chunk,

View File

@ -60,6 +60,103 @@ namespace http {
there was one. If an error is set, the value is propagated to
the caller of the parser.
@par Derived Class Requirements
@code
template<bool isRequest>
class derived
: public basic_parser<isRequest, derived<isRequest>>
{
private:
// The friend declaration is needed,
// otherwise the callbacks must be made public.
friend class basic_parser<isRequest, derived>;
/// Called after receiving the request-line (isRequest == true).
void
on_request_impl(
verb method, // The method verb, verb::unknown if no match
string_view method_str, // The method as a string
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_impl(
int code, // 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_impl(
field f, // The known-field enumeration constant
string_view name, // The field name string.
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_impl(
error_code& ec); // The error returned to the caller, if any
/// Called just before processing the body, if a body exists.
void
on_body_init_impl(
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.
//!
//! This is used when there is no chunked transfer coding.
//!
//! The function returns the number of bytes consumed from the
//! input buffer. Any input octets not consumed will be will be
//! presented on subsequent calls.
//!
std::size_t
on_body_impl(
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_header_impl(
std::uint64_t size, // The size of the upcoming chunk,
// or zero for the last chunk
string_view extension, // The chunk extensions (may be empty)
error_code& ec); // The error returned to the caller, if any
/// Called to deliver the chunk body.
//!
//! This is used when there is a chunked transfer coding. The
//! implementation will automatically remove the encoding before
//! calling this function.
//!
//! The function returns the number of bytes consumed from the
//! input buffer. Any input octets not consumed will be will be
//! presented on subsequent calls.
//!
std::size_t
on_chunk_body_impl(
std::uint64_t remain, // The number of bytes remaining in the chunk,
// including what is being passed here.
// or zero for the last chunk
string_view body, // The next piece of the chunk body
error_code& ec); // The error returned to the caller, if any
/// Called when the complete message is parsed.
void
on_finish_impl(error_code& ec);
public:
derived() = default;
};
@endcode
@tparam isRequest A `bool` indicating whether the parser will be
presented with request or response message.

View File

@ -257,6 +257,9 @@ public:
/** Returns the value for a field, or throws an exception.
If more than one field with the specified name exists, the
first field defined by insertion order is returned.
@param name The name of the field.
@return The field value.
@ -268,6 +271,9 @@ public:
/** Returns the value for a field, or throws an exception.
If more than one field with the specified name exists, the
first field defined by insertion order is returned.
@param name The name of the field.
@return The field value.

View File

@ -156,11 +156,11 @@ public:
{
using boost::asio::buffer_size;
using boost::asio::buffer_copy;
auto const n = buffer_size(buffers);
auto const len = body_.size();
auto const extra = buffer_size(buffers);
auto const size = body_.size();
try
{
body_.resize(len + n);
body_.resize(size + extra);
}
catch(std::exception const&)
{
@ -168,8 +168,16 @@ public:
return 0;
}
ec.assign(0, ec.category());
return buffer_copy(boost::asio::buffer(
&body_[0] + len, n), buffers);
CharT* dest = &body_[size];
for(boost::asio::const_buffer b : buffers)
{
using boost::asio::buffer_cast;
auto const len = boost::asio::buffer_size(b);
Traits::copy(
dest, buffer_cast<CharT const*>(b), len);
dest += len;
}
return extra;
}
void

View File

@ -27,15 +27,15 @@ struct Body
struct value_type;
/// The algorithm used for extracting buffers
using reader = BodyReader;
class reader;
/// The algorithm used for inserting buffers
using writer = BodyWriter;
class writer;
/// Returns the body's payload size
static
std::uint64_t
size(value_type const& v);
size(value_type const& body);
};
static_assert(is_body<Body>::value, "");