mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 02:55:50 +00:00
Separate beast::http::body from beast::http::message (RIPD-660):
This changes the http::message object to no longer contain a body. It modifies the parser to store the body in a separate object, or to pass the body data to a functor. This allows the body to be stored in more flexible ways. For example, in HTTP responses the body can be generated procedurally instead of being required to exist entirely in memory at once.
This commit is contained in:
@@ -50,17 +50,16 @@ public:
|
|||||||
body (body const&) = delete;
|
body (body const&) = delete;
|
||||||
body& operator= (body const&) = delete;
|
body& operator= (body const&) = delete;
|
||||||
|
|
||||||
|
template <class = void>
|
||||||
|
void
|
||||||
|
clear();
|
||||||
|
|
||||||
void
|
void
|
||||||
write (void const* data, std::size_t bytes);
|
write (void const* data, std::size_t bytes);
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
template <class ConstBufferSequence>
|
||||||
void
|
void
|
||||||
write (ConstBufferSequence const& buffers)
|
write (ConstBufferSequence const& buffers);
|
||||||
{
|
|
||||||
for (auto const& buffer : buffers)
|
|
||||||
write (boost::asio::buffer_cast <void const*> (buffer),
|
|
||||||
boost::asio::buffer_size (buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
std::size_t
|
||||||
size() const;
|
size() const;
|
||||||
@@ -92,8 +91,9 @@ body::body()
|
|||||||
|
|
||||||
inline
|
inline
|
||||||
body::body (body&& other)
|
body::body (body&& other)
|
||||||
|
: buf_ (std::move(other.buf_))
|
||||||
{
|
{
|
||||||
buf_ = std::move(other.buf_);
|
other.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
@@ -101,9 +101,17 @@ body&
|
|||||||
body::operator= (body&& other)
|
body::operator= (body&& other)
|
||||||
{
|
{
|
||||||
buf_ = std::move(other.buf_);
|
buf_ = std::move(other.buf_);
|
||||||
|
other.clear();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class>
|
||||||
|
void
|
||||||
|
body::clear()
|
||||||
|
{
|
||||||
|
buf_ = std::make_unique <buffer_type>();
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
body::write (void const* data, std::size_t bytes)
|
body::write (void const* data, std::size_t bytes)
|
||||||
@@ -112,6 +120,15 @@ body::write (void const* data, std::size_t bytes)
|
|||||||
boost::asio::const_buffers_1 (data, bytes)));
|
boost::asio::const_buffers_1 (data, bytes)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ConstBufferSequence>
|
||||||
|
void
|
||||||
|
body::write (ConstBufferSequence const& buffers)
|
||||||
|
{
|
||||||
|
for (auto const& buffer : buffers)
|
||||||
|
write (boost::asio::buffer_cast <void const*> (buffer),
|
||||||
|
boost::asio::buffer_size (buffer));
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
std::size_t
|
std::size_t
|
||||||
body::size() const
|
body::size() const
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#define BEAST_HTTP_MESSAGE_H_INCLUDED
|
#define BEAST_HTTP_MESSAGE_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/http/basic_parser.h>
|
#include <beast/http/basic_parser.h>
|
||||||
#include <beast/http/body.h>
|
|
||||||
#include <beast/http/method.h>
|
#include <beast/http/method.h>
|
||||||
#include <beast/http/headers.h>
|
#include <beast/http/headers.h>
|
||||||
#include <beast/utility/ci_char_traits.h>
|
#include <beast/utility/ci_char_traits.h>
|
||||||
@@ -72,9 +71,8 @@ public:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Memberspaces
|
// Memberspace
|
||||||
beast::http::headers headers;
|
beast::http::headers headers;
|
||||||
beast::http::body body;
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
request() const
|
request() const
|
||||||
@@ -213,7 +211,6 @@ message::message (message&& other)
|
|||||||
, keep_alive_ (other.keep_alive_)
|
, keep_alive_ (other.keep_alive_)
|
||||||
, upgrade_ (other.upgrade_)
|
, upgrade_ (other.upgrade_)
|
||||||
, headers (std::move(other.headers))
|
, headers (std::move(other.headers))
|
||||||
, body (std::move(other.body))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,33 +227,32 @@ message::operator= (message&& other)
|
|||||||
keep_alive_ = other.keep_alive_;
|
keep_alive_ = other.keep_alive_;
|
||||||
upgrade_ = other.upgrade_;
|
upgrade_ = other.upgrade_;
|
||||||
headers = std::move(other.headers);
|
headers = std::move(other.headers);
|
||||||
body = std::move(other.body);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template <class AsioStreamBuf>
|
template <class Streambuf>
|
||||||
void
|
void
|
||||||
write (AsioStreamBuf& stream, std::string const& s)
|
write (Streambuf& stream, std::string const& s)
|
||||||
{
|
{
|
||||||
stream.commit (boost::asio::buffer_copy (
|
stream.commit (boost::asio::buffer_copy (
|
||||||
stream.prepare (s.size()), boost::asio::buffer(s)));
|
stream.prepare (s.size()), boost::asio::buffer(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class AsioStreamBuf>
|
template <class Streambuf>
|
||||||
void
|
void
|
||||||
write (AsioStreamBuf& stream, char const* s)
|
write (Streambuf& stream, char const* s)
|
||||||
{
|
{
|
||||||
auto const len (::strlen(s));
|
auto const len (::strlen(s));
|
||||||
stream.commit (boost::asio::buffer_copy (
|
stream.commit (boost::asio::buffer_copy (
|
||||||
stream.prepare (len), boost::asio::buffer (s, len)));
|
stream.prepare (len), boost::asio::buffer (s, len)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class AsioStreamBuf>
|
template <class Streambuf>
|
||||||
void
|
void
|
||||||
write (AsioStreamBuf& stream, message const& m)
|
write (Streambuf& stream, message const& m)
|
||||||
{
|
{
|
||||||
if (m.request())
|
if (m.request())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#define BEAST_HTTP_PARSER_H_INCLUDED
|
#define BEAST_HTTP_PARSER_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/http/message.h>
|
#include <beast/http/message.h>
|
||||||
|
#include <beast/http/body.h>
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -34,15 +36,33 @@ class parser : public beast::http::basic_parser
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::reference_wrapper <message> message_;
|
std::reference_wrapper <message> message_;
|
||||||
|
std::function<void(void const*, std::size_t)> write_body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Construct a parser for HTTP request or response.
|
/** Construct a parser for HTTP request or response.
|
||||||
The result is stored in the passed message.
|
The headers plus request or status line are stored in message.
|
||||||
|
The content-body, if any, is passed as a series of calls to
|
||||||
|
the write_body function. Transfer encodings are applied before
|
||||||
|
any data is passed to the write_body function.
|
||||||
*/
|
*/
|
||||||
parser (message& m, bool request)
|
parser (std::function<void(void const*, std::size_t)> write_body,
|
||||||
|
message& m, bool request)
|
||||||
|
: beast::http::basic_parser (request)
|
||||||
|
, message_(m)
|
||||||
|
, write_body_(std::move(write_body))
|
||||||
|
{
|
||||||
|
message_.get().request(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
parser (message& m, body& b, bool request)
|
||||||
: beast::http::basic_parser (request)
|
: beast::http::basic_parser (request)
|
||||||
, message_(m)
|
, message_(m)
|
||||||
{
|
{
|
||||||
|
write_body_ = [&b](void const* data, std::size_t size)
|
||||||
|
{
|
||||||
|
b.write(data, size);
|
||||||
|
};
|
||||||
|
|
||||||
message_.get().request(request);
|
message_.get().request(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +155,7 @@ parser::operator= (parser&& other)
|
|||||||
|
|
||||||
template <class>
|
template <class>
|
||||||
void
|
void
|
||||||
parser::do_start ()
|
parser::do_start()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +196,7 @@ template <class>
|
|||||||
void
|
void
|
||||||
parser::do_body (void const* data, std::size_t bytes)
|
parser::do_body (void const* data, std::size_t bytes)
|
||||||
{
|
{
|
||||||
message_.get().body.write (data, bytes);
|
write_body_(data, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class>
|
template <class>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <beast/http/message.h>
|
#include <beast/http/message.h>
|
||||||
#include <beast/http/parser.h>
|
#include <beast/http/parser.h>
|
||||||
#include <beast/unit_test/suite.h>
|
#include <beast/unit_test/suite.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
@@ -31,7 +32,8 @@ public:
|
|||||||
request (std::string const& text)
|
request (std::string const& text)
|
||||||
{
|
{
|
||||||
message m;
|
message m;
|
||||||
parser p (m, true);
|
body b;
|
||||||
|
parser p (m, b, true);
|
||||||
auto result (p.write (boost::asio::buffer(text)));
|
auto result (p.write (boost::asio::buffer(text)));
|
||||||
p.write_eof();
|
p.write_eof();
|
||||||
return std::make_pair (std::move(m), result.first);
|
return std::make_pair (std::move(m), result.first);
|
||||||
@@ -65,7 +67,8 @@ public:
|
|||||||
"\r\n"
|
"\r\n"
|
||||||
;
|
;
|
||||||
message m;
|
message m;
|
||||||
parser p (m, true);
|
body b;
|
||||||
|
parser p (m, b, true);
|
||||||
auto result (p.write (boost::asio::buffer(text)));
|
auto result (p.write (boost::asio::buffer(text)));
|
||||||
expect (! result.first);
|
expect (! result.first);
|
||||||
auto result2 (p.write_eof());
|
auto result2 (p.write_eof());
|
||||||
@@ -80,7 +83,8 @@ public:
|
|||||||
"\r\n"
|
"\r\n"
|
||||||
;
|
;
|
||||||
message m;
|
message m;
|
||||||
parser p (m, true);
|
body b;
|
||||||
|
parser p (m, b, true);
|
||||||
auto result = p.write (boost::asio::buffer(text));
|
auto result = p.write (boost::asio::buffer(text));
|
||||||
if (expect (result.first))
|
if (expect (result.first))
|
||||||
expect (result.first.message() == "invalid HTTP method");
|
expect (result.first.message() == "invalid HTTP method");
|
||||||
|
|||||||
Reference in New Issue
Block a user