mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
@ -3,6 +3,7 @@ Version 64:
|
||||
* Simplify buffered_read_stream composed op
|
||||
* Simplify ssl teardown composed op
|
||||
* Simplify websocket write_op
|
||||
* Exemplars are compiled code
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -82,6 +82,7 @@
|
||||
[import ../example/server-framework/file_body.hpp]
|
||||
[import ../example/websocket-client/websocket_client.cpp]
|
||||
|
||||
[import ../test/exemplars.cpp]
|
||||
[import ../test/core/doc_snippets.cpp]
|
||||
[import ../test/http/doc_snippets.cpp]
|
||||
[import ../test/websocket/doc_snippets.cpp]
|
||||
|
@ -69,22 +69,6 @@ In this table:
|
||||
|
||||
[heading Exemplar]
|
||||
|
||||
```
|
||||
struct Body
|
||||
{
|
||||
using value_type = implementation_defined;
|
||||
|
||||
/// The algorithm used for extracting buffers
|
||||
class reader;
|
||||
|
||||
/// The algorithm used for inserting buffers
|
||||
class writer;
|
||||
|
||||
/// Returns the body's payload size
|
||||
static
|
||||
std::uint64_t
|
||||
size(value_type const& v);
|
||||
}
|
||||
```
|
||||
[concept_Body]
|
||||
|
||||
[endsect]
|
||||
|
@ -112,78 +112,8 @@ In this table:
|
||||
]
|
||||
]
|
||||
|
||||
[note
|
||||
Definitions for required [*BodyReader] member functions may
|
||||
be declared inline so the generated code can become part of
|
||||
the implementation.
|
||||
]
|
||||
|
||||
[heading Exemplar]
|
||||
|
||||
```
|
||||
struct BodyReader
|
||||
{
|
||||
public:
|
||||
/** Controls when the implementation requests buffers.
|
||||
|
||||
If false, the implementation will request the first buffer
|
||||
immediately and try to serialize both the header and some
|
||||
or all of the body in a single buffer.
|
||||
*/
|
||||
using is_deferred = std::false_type;
|
||||
|
||||
/// The type of buffer returned by `get`.
|
||||
using const_buffers_type = boost::asio::const_buffers_1;
|
||||
|
||||
/** Construct the reader.
|
||||
|
||||
@param msg The message whose body is to be retrieved.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
explicit
|
||||
BodyReader(message<isRequest, Body, Headers> const& msg);
|
||||
|
||||
/** Initialization.
|
||||
|
||||
Called once immediately after construction.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
}
|
||||
|
||||
/** Returns the next buffer in the body.
|
||||
|
||||
@li If the return value is `boost::none` (unseated optional) and
|
||||
`ec` does not contain an error, this indicates the end of the
|
||||
body, no more buffers are present.
|
||||
|
||||
@li If the optional contains a value, the first element of the
|
||||
pair represents a @b ConstBufferSequence containing one or
|
||||
more octets of the body data. The second element indicates
|
||||
whether or not there are additional octets of body data.
|
||||
A value of `true` means there is more data, and that the
|
||||
implementation will perform a subsequent call to `get`.
|
||||
A value of `false` means there is no more body data.
|
||||
|
||||
@li If `ec` contains an error code, the return value is ignored.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec);
|
||||
|
||||
/** Called after `get` indicates there are no more buffers.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
finish(error_code& ec);
|
||||
};
|
||||
```
|
||||
[concept_BodyReader]
|
||||
|
||||
[endsect]
|
||||
|
@ -20,7 +20,7 @@ representation:
|
||||
to compress it first.
|
||||
* Saving body data to a file
|
||||
|
||||
In the table below:
|
||||
In this table:
|
||||
|
||||
* `X` denotes a type meeting the requirements of [*BodyWriter].
|
||||
|
||||
@ -88,59 +88,8 @@ In the table below:
|
||||
]
|
||||
]
|
||||
|
||||
[note
|
||||
Definitions for required [*BodyReader] member functions may
|
||||
be declared inline so the generated code can become part of
|
||||
the implementation.
|
||||
]
|
||||
|
||||
[heading Exemplar]
|
||||
|
||||
```
|
||||
struct BodyWriter
|
||||
{
|
||||
/** Construct the writer.
|
||||
|
||||
@param msg The message whose body is to be stored.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
explicit
|
||||
BodyWriter(message<isRequest, Body, Fields>& msg);
|
||||
|
||||
/** Initialization.
|
||||
|
||||
Called once immediately before storing any buffers.
|
||||
|
||||
@param content_length The content length if known, else `boost::none`.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
init(boost::optional<std::uint64_t> content_length, error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
}
|
||||
|
||||
/** Store buffers.
|
||||
|
||||
This is called zero or more times with parsed body octets.
|
||||
|
||||
@param buffers The constant buffer sequence to store.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
put(ConstBufferSequence const& buffers, error_code& ec);
|
||||
|
||||
/** Called when the body is complete.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
finish(error_code& ec);
|
||||
};
|
||||
```
|
||||
[concept_BodyWriter]
|
||||
|
||||
[endsect]
|
||||
|
@ -31,7 +31,7 @@ implementation strategies:
|
||||
size of the character sequence. This is the implementation approach
|
||||
currently offered by __multi_buffer__.
|
||||
|
||||
In the table below:
|
||||
In this table:
|
||||
|
||||
* `X` denotes a dynamic buffer class.
|
||||
* `a` denotes a value of type `X`.
|
||||
|
@ -127,54 +127,6 @@ In this table:
|
||||
|
||||
[heading Exemplar]
|
||||
|
||||
```
|
||||
class Fields
|
||||
{
|
||||
protected:
|
||||
/** Set or clear the method string.
|
||||
|
||||
@note Only called for requests.
|
||||
*/
|
||||
void set_method_impl(string_view s);
|
||||
|
||||
/** Set or clear the target string.
|
||||
|
||||
@note Only called for requests.
|
||||
*/
|
||||
void set_target_impl(string_view s);
|
||||
|
||||
/** Set or clear the reason string.
|
||||
|
||||
@note Only called for responses.
|
||||
*/
|
||||
void set_reason_impl(string_view s);
|
||||
|
||||
/** Returns the request-method string.
|
||||
|
||||
@note Only called for requests.
|
||||
*/
|
||||
string_view get_method_impl() const;
|
||||
|
||||
/** Returns the request-target string.
|
||||
|
||||
@note Only called for requests.
|
||||
*/
|
||||
string_view get_target_impl() const;
|
||||
|
||||
/** Returns the response reason-phrase string.
|
||||
|
||||
@note Only called for responses.
|
||||
*/
|
||||
string_view get_reason_impl() const;
|
||||
|
||||
/** Updates the payload metadata.
|
||||
|
||||
@param b `true` if chunked
|
||||
|
||||
@param n The content length if known, otherwise `boost::none`
|
||||
*/
|
||||
void prepare_payload_impl(bool b, boost::optional<std::uint64_t> n)
|
||||
};
|
||||
```
|
||||
[concept_Fields]
|
||||
|
||||
[endsect]
|
||||
|
@ -98,30 +98,6 @@ In this table:
|
||||
|
||||
[heading Exemplar]
|
||||
|
||||
```
|
||||
struct FieldsReader
|
||||
{
|
||||
// The type of buffers returned by `get`
|
||||
using const_buffers_type = implementation-defined;
|
||||
|
||||
// Constructor for requests
|
||||
FieldsReader(F const& f, unsigned version, verb method);
|
||||
|
||||
// Constructor for responses
|
||||
FieldsReader(F const& f, unsigned version, unsigned status);
|
||||
|
||||
// Returns `true` if the payload uses the chunked Transfer-Encoding
|
||||
bool
|
||||
chunked();
|
||||
|
||||
// Returns `true` if keep-alive is indicated
|
||||
bool
|
||||
keep_alive();
|
||||
|
||||
// Returns the serialized header buffers
|
||||
const_buffers_type
|
||||
get();
|
||||
};
|
||||
```
|
||||
[concept_FieldsReader]
|
||||
|
||||
[endsect]
|
||||
|
@ -22,6 +22,7 @@ if ((NOT "${VARIANT}" STREQUAL "coverage") AND
|
||||
../extras/beast/unit_test/main.cpp
|
||||
config.cpp
|
||||
core.cpp
|
||||
exemplars.cpp
|
||||
http.cpp
|
||||
version.cpp
|
||||
websocket.cpp
|
||||
|
@ -13,6 +13,9 @@ compile config.cpp : <variant>coverage:<build>no
|
||||
compile core.cpp : <variant>coverage:<build>no
|
||||
<variant>ubasan:<build>no : ;
|
||||
|
||||
compile exemplars.cpp : <variant>coverage:<build>no
|
||||
<variant>ubasan:<build>no : ;
|
||||
|
||||
compile http.cpp : <variant>coverage:<build>no
|
||||
<variant>ubasan:<build>no : ;
|
||||
|
||||
|
280
test/exemplars.cpp
Normal file
280
test/exemplars.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
#include <beast/core/error.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/type_traits.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class BodyReader;
|
||||
class BodyWriter;
|
||||
|
||||
//[concept_Body
|
||||
|
||||
struct Body
|
||||
{
|
||||
// The type of message::body when used
|
||||
struct value_type;
|
||||
|
||||
/// The algorithm used for extracting buffers
|
||||
using reader = BodyReader;
|
||||
|
||||
/// The algorithm used for inserting buffers
|
||||
using writer = BodyWriter;
|
||||
|
||||
/// Returns the body's payload size
|
||||
static
|
||||
std::uint64_t
|
||||
size(value_type const& v);
|
||||
};
|
||||
|
||||
static_assert(is_body<Body>::value, "");
|
||||
|
||||
//]
|
||||
|
||||
struct Body_BodyReader {
|
||||
struct value_type{};
|
||||
//[concept_BodyReader
|
||||
|
||||
struct BodyReader
|
||||
{
|
||||
public:
|
||||
/** Controls when the implementation requests buffers.
|
||||
|
||||
If false, the implementation will request the first buffer
|
||||
immediately and try to serialize both the header and some
|
||||
or all of the body in a single buffer.
|
||||
*/
|
||||
using is_deferred = std::false_type;
|
||||
|
||||
/// The type of buffer returned by `get`.
|
||||
using const_buffers_type = boost::asio::const_buffers_1;
|
||||
|
||||
/** Construct the reader.
|
||||
|
||||
@param msg The message whose body is to be retrieved.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
explicit
|
||||
BodyReader(message<isRequest, Body, Headers> const& msg);
|
||||
|
||||
/** Initialization.
|
||||
|
||||
Called once immediately after construction.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
}
|
||||
|
||||
/** Returns the next buffer in the body.
|
||||
|
||||
@li If the return value is `boost::none` (unseated optional) and
|
||||
`ec` does not contain an error, this indicates the end of the
|
||||
body, no more buffers are present.
|
||||
|
||||
@li If the optional contains a value, the first element of the
|
||||
pair represents a @b ConstBufferSequence containing one or
|
||||
more octets of the body data. The second element indicates
|
||||
whether or not there are additional octets of body data.
|
||||
A value of `true` means there is more data, and that the
|
||||
implementation will perform a subsequent call to `get`.
|
||||
A value of `false` means there is no more body data.
|
||||
|
||||
@li If `ec` contains an error code, the return value is ignored.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
boost::optional<std::pair<const_buffers_type, bool>>
|
||||
get(error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
|
||||
return boost::none; // for exposition only
|
||||
}
|
||||
|
||||
/** Called after `get` indicates there are no more buffers.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
finish(error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
}
|
||||
};
|
||||
|
||||
//]
|
||||
using reader = BodyReader;
|
||||
};
|
||||
|
||||
static_assert(is_body_reader<Body_BodyReader>::value, "");
|
||||
|
||||
struct Body_BodyWriter {
|
||||
struct value_type{};
|
||||
//[concept_BodyWriter
|
||||
|
||||
struct BodyWriter
|
||||
{
|
||||
/** Construct the writer.
|
||||
|
||||
@param msg The message whose body is to be stored.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
explicit
|
||||
BodyWriter(message<isRequest, Body, Fields>& msg);
|
||||
|
||||
/** Initialization.
|
||||
|
||||
Called once immediately before storing any buffers.
|
||||
|
||||
@param content_length The content length if known, else `boost::none`.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
init(boost::optional<std::uint64_t> content_length, error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
}
|
||||
|
||||
/** Store buffers.
|
||||
|
||||
This is called zero or more times with parsed body octets.
|
||||
|
||||
@param buffers The constant buffer sequence to store.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
put(ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
}
|
||||
|
||||
/** Called when the body is complete.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
void
|
||||
finish(error_code& ec)
|
||||
{
|
||||
// The specification requires this to indicate "no error"
|
||||
ec = {};
|
||||
}
|
||||
};
|
||||
|
||||
//]
|
||||
using writer = BodyWriter;
|
||||
};
|
||||
|
||||
static_assert(is_body_writer<Body_BodyWriter>::value, "");
|
||||
|
||||
//[concept_Fields
|
||||
|
||||
class Fields
|
||||
{
|
||||
public:
|
||||
struct reader;
|
||||
|
||||
protected:
|
||||
/** Set or clear the method string.
|
||||
|
||||
@note Only called for requests.
|
||||
*/
|
||||
void set_method_impl(string_view s);
|
||||
|
||||
/** Set or clear the target string.
|
||||
|
||||
@note Only called for requests.
|
||||
*/
|
||||
void set_target_impl(string_view s);
|
||||
|
||||
/** Set or clear the reason string.
|
||||
|
||||
@note Only called for responses.
|
||||
*/
|
||||
void set_reason_impl(string_view s);
|
||||
|
||||
/** Returns the request-method string.
|
||||
|
||||
@note Only called for requests.
|
||||
*/
|
||||
string_view get_method_impl() const;
|
||||
|
||||
/** Returns the request-target string.
|
||||
|
||||
@note Only called for requests.
|
||||
*/
|
||||
string_view get_target_impl() const;
|
||||
|
||||
/** Returns the response reason-phrase string.
|
||||
|
||||
@note Only called for responses.
|
||||
*/
|
||||
string_view get_reason_impl() const;
|
||||
|
||||
/** Updates the payload metadata.
|
||||
|
||||
@param b `true` if chunked
|
||||
|
||||
@param n The content length if known, otherwise `boost::none`
|
||||
*/
|
||||
void prepare_payload_impl(bool b, boost::optional<std::uint64_t> n);
|
||||
};
|
||||
|
||||
static_assert(is_fields<Fields>::value, "");
|
||||
|
||||
//]
|
||||
|
||||
struct Fields_FieldsReader {
|
||||
using F = Fields_FieldsReader;
|
||||
//[concept_FieldsReader
|
||||
|
||||
struct FieldsReader
|
||||
{
|
||||
// The type of buffers returned by `get`
|
||||
struct const_buffers_type;
|
||||
|
||||
// Constructor for requests
|
||||
FieldsReader(F const& f, unsigned version, verb method);
|
||||
|
||||
// Constructor for responses
|
||||
FieldsReader(F const& f, unsigned version, unsigned status);
|
||||
|
||||
// Returns `true` if the payload uses the chunked Transfer-Encoding
|
||||
bool
|
||||
chunked();
|
||||
|
||||
// Returns `true` if keep-alive is indicated
|
||||
bool
|
||||
keep_alive();
|
||||
|
||||
// Returns the serialized header buffers
|
||||
const_buffers_type
|
||||
get();
|
||||
};
|
||||
|
||||
//]
|
||||
};
|
||||
|
||||
} // http
|
||||
} // beast
|
Reference in New Issue
Block a user