forked from boostorg/beast
96 lines
4.5 KiB
Plaintext
96 lines
4.5 KiB
Plaintext
[/
|
|
Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
|
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
]
|
|
|
|
[section:serializer_buffers Buffer-Oriented Serializing]
|
|
|
|
In extreme cases, users may wish to create an instance of __serializer__
|
|
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.
|
|
|
|
After the serializer is created, the buffers are produced by first calling
|
|
[link beast.ref.http__serializer.get `serializer::get`]
|
|
to obtain a buffer sequence, and then calling
|
|
[link beast.ref.http__serializer.consume `serializer::consume`]
|
|
to indicate how many bytes in the buffer sequence were consumed.
|
|
This advanced the internal state of the serializer and prepares the
|
|
next set of buffers for delivery.
|
|
[link beast.ref.http__serializer.get `serializer::get`]
|
|
takes an error code parameter and invokes a visitor argument with the
|
|
error code and buffer of unspecified type. In C++14 this is easily
|
|
expressed with a generic lambda. The function
|
|
[link beast.ref.http__serializer.is_done `serializer::is_done`]
|
|
will return `true` when all the buffers have been produced. This C++14
|
|
example prints the buffers to standard output:
|
|
|
|
[http_snippet_14]
|
|
|
|
Generic lambda expressions are only available in C++14 or later. A functor
|
|
with a templated function call operator is necessary to use C++11 as shown:
|
|
|
|
[http_snippet_15]
|
|
|
|
[heading Split Serialization]
|
|
|
|
In some cases, such as the handling of the
|
|
[@https://tools.ietf.org/html/rfc7231#section-5.1.1 Expect: 100-continue]
|
|
field, it may be desired to first serialize the header, perform some other
|
|
action, and then continue with serialization of the body. This is
|
|
accomplished by calling
|
|
[link beast.ref.http__serializer.split `serializer::split`]
|
|
with a boolean indicating that when buffers are produced, the last buffer
|
|
containing serialized header octets will not contain any octets corresponding
|
|
to the body. The function
|
|
[link beast.ref.http__serializer.is_header_done `serializer::is_header_done`]
|
|
informs the caller whether the header has completed serialization. In this
|
|
C++14 example we print the header first, followed by the body:
|
|
|
|
[http_snippet_16]
|
|
|
|
[heading Chunk Decorators]
|
|
|
|
When the message used to construct the serializer indicates the chunked
|
|
transfer encoding, the serializer will automatically generate the proper
|
|
encoding in the output buffers. __rfc7230__ defines additional fields
|
|
called the
|
|
[@https://tools.ietf.org/html/rfc7230#section-4.1.1 chunk extensions]
|
|
in chunks with body octets, and the
|
|
[@https://tools.ietf.org/html/rfc7230#section-4.1.2 chunked trailer part]
|
|
for the final chunk. Applications that wish to emit chunk extensions
|
|
and trailers may instantiate the serializer with a "chunk decorator" type,
|
|
and pass an instance of the type upon construction. This decorator is
|
|
a function object which, when invoked with a __ConstBufferSequence__,
|
|
returns a
|
|
[link beast.ref.string_view `string_view`] containing either the extensions
|
|
or the trailer. For chunks containing body data, the passed buffer will
|
|
contain one or more corresponding body octets. The decorator may use this
|
|
information as needed. For example, to compute a digest on the data and
|
|
store it as a chunk extension. For the trailers, the serializer will
|
|
invoke the decorator with a buffer sequence of size zero. Or more
|
|
specifically, with an object of type
|
|
[@http://www.boost.org/doc/html/boost_asio/reference/null_buffers.html `boost::asio::null_buffers`].
|
|
|
|
For body chunks the string returned by the decorator must follow the
|
|
[@https://tools.ietf.org/html/rfc7230#section-4.1.1 correct syntax]
|
|
for the entire chunk extension. For the trailer, the returned string
|
|
should consist of zero or more lines ending in a CRLF and containing
|
|
a field name/value pair in the format prescribed by __rfc7230__. It
|
|
is the responsibility of the decorator to manage returned string buffers.
|
|
The implementation guarantees it will not reference previous strings
|
|
after subsequent calls.
|
|
|
|
Here, we declare a decorator which sets an extension variable `x` equal
|
|
to the size of the chunk in bytes, and returns a single trailer field:
|
|
|
|
[http_snippet_17]
|
|
|
|
[endsect]
|