mirror of
https://github.com/PurpleI2P/Boost-for-Android-Prebuilt
synced 2025-01-09 06:18:03 +00:00
371 lines
12 KiB
C++
371 lines
12 KiB
C++
//
|
|
// Copyright (c) 2016-2019 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)
|
|
//
|
|
// Official repository: https://github.com/boostorg/beast
|
|
//
|
|
|
|
#ifndef BOOST_BEAST_HTTP_SERIALIZER_HPP
|
|
#define BOOST_BEAST_HTTP_SERIALIZER_HPP
|
|
|
|
#include <boost/beast/core/detail/config.hpp>
|
|
#include <boost/beast/core/buffers_cat.hpp>
|
|
#include <boost/beast/core/buffers_prefix.hpp>
|
|
#include <boost/beast/core/buffers_suffix.hpp>
|
|
#include <boost/beast/core/string.hpp>
|
|
#include <boost/beast/core/detail/variant.hpp>
|
|
#include <boost/beast/http/message.hpp>
|
|
#include <boost/beast/http/chunk_encode.hpp>
|
|
#include <boost/asio/buffer.hpp>
|
|
#include <boost/optional.hpp>
|
|
|
|
namespace boost {
|
|
namespace beast {
|
|
namespace http {
|
|
|
|
/** Provides buffer oriented HTTP message serialization functionality.
|
|
|
|
An object of this type is used to serialize a complete
|
|
HTTP message into a sequence of octets. To use this class,
|
|
construct an instance with the message to be serialized.
|
|
The implementation will automatically perform chunk encoding
|
|
if the contents of the message indicate that chunk encoding
|
|
is required.
|
|
|
|
Chunked output produced by the serializer never contains chunk
|
|
extensions or trailers, and the location of chunk boundaries
|
|
is not specified. If callers require chunk extensions, trailers,
|
|
or control over the exact contents of each chunk they should
|
|
use the serializer to write just the message header, and then
|
|
assume control over serializing the chunked payload by using
|
|
the chunk buffer sequence types @ref chunk_body, @ref chunk_crlf,
|
|
@ref chunk_header, and @ref chunk_last.
|
|
|
|
@tparam isRequest `true` if the message is a request.
|
|
|
|
@tparam Body The body type of the message.
|
|
|
|
@tparam Fields The type of fields in the message.
|
|
*/
|
|
template<
|
|
bool isRequest,
|
|
class Body,
|
|
class Fields = fields>
|
|
class serializer
|
|
{
|
|
public:
|
|
static_assert(is_body<Body>::value,
|
|
"Body type requirements not met");
|
|
|
|
static_assert(is_body_writer<Body>::value,
|
|
"BodyWriter type requirements not met");
|
|
|
|
/** The type of message this serializer uses
|
|
|
|
This may be const or non-const depending on the
|
|
implementation of the corresponding <em>BodyWriter</em>.
|
|
*/
|
|
#if BOOST_BEAST_DOXYGEN
|
|
using value_type = __implementation_defined__;
|
|
#else
|
|
using value_type = typename std::conditional<
|
|
std::is_constructible<typename Body::writer,
|
|
header<isRequest, Fields>&,
|
|
typename Body::value_type&>::value &&
|
|
! std::is_constructible<typename Body::writer,
|
|
header<isRequest, Fields> const&,
|
|
typename Body::value_type const&>::value,
|
|
message<isRequest, Body, Fields>,
|
|
message<isRequest, Body, Fields> const>::type;
|
|
#endif
|
|
|
|
private:
|
|
enum
|
|
{
|
|
do_construct = 0,
|
|
|
|
do_init = 10,
|
|
do_header_only = 20,
|
|
do_header = 30,
|
|
do_body = 40,
|
|
|
|
do_init_c = 50,
|
|
do_header_only_c = 60,
|
|
do_header_c = 70,
|
|
do_body_c = 80,
|
|
do_final_c = 90,
|
|
#ifndef BOOST_BEAST_NO_BIG_VARIANTS
|
|
do_body_final_c = 100,
|
|
do_all_c = 110,
|
|
#endif
|
|
|
|
do_complete = 120
|
|
};
|
|
|
|
void fwrinit(std::true_type);
|
|
void fwrinit(std::false_type);
|
|
|
|
template<std::size_t, class Visit>
|
|
void
|
|
do_visit(error_code& ec, Visit& visit);
|
|
|
|
using writer = typename Body::writer;
|
|
|
|
using cb1_t = buffers_suffix<typename
|
|
Fields::writer::const_buffers_type>; // header
|
|
using pcb1_t = buffers_prefix_view<cb1_t const&>;
|
|
|
|
using cb2_t = buffers_suffix<buffers_cat_view<
|
|
typename Fields::writer::const_buffers_type,// header
|
|
typename writer::const_buffers_type>>; // body
|
|
using pcb2_t = buffers_prefix_view<cb2_t const&>;
|
|
|
|
using cb3_t = buffers_suffix<
|
|
typename writer::const_buffers_type>; // body
|
|
using pcb3_t = buffers_prefix_view<cb3_t const&>;
|
|
|
|
using cb4_t = buffers_suffix<buffers_cat_view<
|
|
typename Fields::writer::const_buffers_type,// header
|
|
detail::chunk_size, // chunk-size
|
|
net::const_buffer, // chunk-ext
|
|
chunk_crlf, // crlf
|
|
typename writer::const_buffers_type, // body
|
|
chunk_crlf>>; // crlf
|
|
using pcb4_t = buffers_prefix_view<cb4_t const&>;
|
|
|
|
using cb5_t = buffers_suffix<buffers_cat_view<
|
|
detail::chunk_size, // chunk-header
|
|
net::const_buffer, // chunk-ext
|
|
chunk_crlf, // crlf
|
|
typename writer::const_buffers_type, // body
|
|
chunk_crlf>>; // crlf
|
|
using pcb5_t = buffers_prefix_view<cb5_t const&>;
|
|
|
|
using cb6_t = buffers_suffix<buffers_cat_view<
|
|
detail::chunk_size, // chunk-header
|
|
net::const_buffer, // chunk-size
|
|
chunk_crlf, // crlf
|
|
typename writer::const_buffers_type, // body
|
|
chunk_crlf, // crlf
|
|
net::const_buffer, // chunk-final
|
|
net::const_buffer, // trailers
|
|
chunk_crlf>>; // crlf
|
|
using pcb6_t = buffers_prefix_view<cb6_t const&>;
|
|
|
|
using cb7_t = buffers_suffix<buffers_cat_view<
|
|
typename Fields::writer::const_buffers_type,// header
|
|
detail::chunk_size, // chunk-size
|
|
net::const_buffer, // chunk-ext
|
|
chunk_crlf, // crlf
|
|
typename writer::const_buffers_type, // body
|
|
chunk_crlf, // crlf
|
|
net::const_buffer, // chunk-final
|
|
net::const_buffer, // trailers
|
|
chunk_crlf>>; // crlf
|
|
using pcb7_t = buffers_prefix_view<cb7_t const&>;
|
|
|
|
using cb8_t = buffers_suffix<buffers_cat_view<
|
|
net::const_buffer, // chunk-final
|
|
net::const_buffer, // trailers
|
|
chunk_crlf>>; // crlf
|
|
using pcb8_t = buffers_prefix_view<cb8_t const&>;
|
|
|
|
value_type& m_;
|
|
writer wr_;
|
|
boost::optional<typename Fields::writer> fwr_;
|
|
beast::detail::variant<
|
|
cb1_t, cb2_t, cb3_t, cb4_t,
|
|
cb5_t ,cb6_t, cb7_t, cb8_t> v_;
|
|
beast::detail::variant<
|
|
pcb1_t, pcb2_t, pcb3_t, pcb4_t,
|
|
pcb5_t ,pcb6_t, pcb7_t, pcb8_t> pv_;
|
|
std::size_t limit_ =
|
|
(std::numeric_limits<std::size_t>::max)();
|
|
int s_ = do_construct;
|
|
bool split_ = false;
|
|
bool header_done_ = false;
|
|
bool more_ = false;
|
|
|
|
public:
|
|
/// Constructor
|
|
serializer(serializer&&) = default;
|
|
|
|
/// Constructor
|
|
serializer(serializer const&) = default;
|
|
|
|
/// Assignment
|
|
serializer& operator=(serializer const&) = delete;
|
|
|
|
/** Constructor
|
|
|
|
The implementation guarantees that the message passed on
|
|
construction will not be accessed until the first call to
|
|
@ref next. This allows the message to be lazily created.
|
|
For example, if the header is filled in before serialization.
|
|
|
|
@param msg A reference to the message to serialize, which must
|
|
remain valid for the lifetime of the serializer. Depending on
|
|
the type of Body used, this may or may not be a `const` reference.
|
|
|
|
@note This function participates in overload resolution only if
|
|
Body::writer is constructible from a `const` message reference.
|
|
*/
|
|
explicit
|
|
serializer(value_type& msg);
|
|
|
|
/// Returns the message being serialized
|
|
value_type&
|
|
get()
|
|
{
|
|
return m_;
|
|
}
|
|
|
|
/// Returns the serialized buffer size limit
|
|
std::size_t
|
|
limit()
|
|
{
|
|
return limit_;
|
|
}
|
|
|
|
/** Set the serialized buffer size limit
|
|
|
|
This function adjusts the limit on the maximum size of the
|
|
buffers passed to the visitor. The new size limit takes effect
|
|
in the following call to @ref next.
|
|
|
|
The default is no buffer size limit.
|
|
|
|
@param limit The new buffer size limit. If this number
|
|
is zero, the size limit is removed.
|
|
*/
|
|
void
|
|
limit(std::size_t limit)
|
|
{
|
|
limit_ = limit > 0 ? limit :
|
|
(std::numeric_limits<std::size_t>::max)();
|
|
}
|
|
|
|
/** Returns `true` if we will pause after writing the complete header.
|
|
*/
|
|
bool
|
|
split()
|
|
{
|
|
return split_;
|
|
}
|
|
|
|
/** Set whether the header and body are written separately.
|
|
|
|
When the split feature is enabled, the implementation will
|
|
write only the octets corresponding to the serialized header
|
|
first. If the header has already been written, this function
|
|
will have no effect on output.
|
|
*/
|
|
void
|
|
split(bool v)
|
|
{
|
|
split_ = v;
|
|
}
|
|
|
|
/** Return `true` if serialization of the header is complete.
|
|
|
|
This function indicates whether or not all buffers containing
|
|
serialized header octets have been retrieved.
|
|
*/
|
|
bool
|
|
is_header_done()
|
|
{
|
|
return header_done_;
|
|
}
|
|
|
|
/** Return `true` if serialization is complete.
|
|
|
|
The operation is complete when all octets corresponding
|
|
to the serialized representation of the message have been
|
|
successfully retrieved.
|
|
*/
|
|
bool
|
|
is_done()
|
|
{
|
|
return s_ == do_complete;
|
|
}
|
|
|
|
/** Returns the next set of buffers in the serialization.
|
|
|
|
This function will attempt to call the `visit` function
|
|
object with a <em>ConstBufferSequence</em> of unspecified type
|
|
representing the next set of buffers in the serialization
|
|
of the message represented by this object.
|
|
|
|
If there are no more buffers in the serialization, the
|
|
visit function will not be called. In this case, no error
|
|
will be indicated, and the function @ref is_done will
|
|
return `true`.
|
|
|
|
@param ec Set to the error, if any occurred.
|
|
|
|
@param visit The function to call. The equivalent function
|
|
signature of this object must be:
|
|
@code
|
|
template<class ConstBufferSequence>
|
|
void visit(error_code&, ConstBufferSequence const&);
|
|
@endcode
|
|
The function is not copied, if no error occurs it will be
|
|
invoked before the call to @ref next returns.
|
|
|
|
*/
|
|
template<class Visit>
|
|
void
|
|
next(error_code& ec, Visit&& visit);
|
|
|
|
/** Consume buffer octets in the serialization.
|
|
|
|
This function should be called after one or more octets
|
|
contained in the buffers provided in the prior call
|
|
to @ref next have been used.
|
|
|
|
After a call to @ref consume, callers should check the
|
|
return value of @ref is_done to determine if the entire
|
|
message has been serialized.
|
|
|
|
@param n The number of octets to consume. This number must
|
|
be greater than zero and no greater than the number of
|
|
octets in the buffers provided in the prior call to @ref next.
|
|
*/
|
|
void
|
|
consume(std::size_t n);
|
|
|
|
/** Provides low-level access to the associated <em>BodyWriter</em>
|
|
|
|
This function provides access to the instance of the writer
|
|
associated with the body and created by the serializer
|
|
upon construction. The behavior of accessing this object
|
|
is defined by the specification of the particular writer
|
|
and its associated body.
|
|
|
|
@return A reference to the writer.
|
|
*/
|
|
writer&
|
|
writer_impl()
|
|
{
|
|
return wr_;
|
|
}
|
|
};
|
|
|
|
/// A serializer for HTTP/1 requests
|
|
template<class Body, class Fields = fields>
|
|
using request_serializer = serializer<true, Body, Fields>;
|
|
|
|
/// A serializer for HTTP/1 responses
|
|
template<class Body, class Fields = fields>
|
|
using response_serializer = serializer<false, Body, Fields>;
|
|
|
|
} // http
|
|
} // beast
|
|
} // boost
|
|
|
|
#include <boost/beast/http/impl/serializer.hpp>
|
|
|
|
#endif
|