diff --git a/src/beast/beast/http/body.h b/src/beast/beast/http/body.h index 16bf77db0..69ac0b85a 100644 --- a/src/beast/beast/http/body.h +++ b/src/beast/beast/http/body.h @@ -50,17 +50,16 @@ public: body (body const&) = delete; body& operator= (body const&) = delete; + template + void + clear(); + void write (void const* data, std::size_t bytes); template void - write (ConstBufferSequence const& buffers) - { - for (auto const& buffer : buffers) - write (boost::asio::buffer_cast (buffer), - boost::asio::buffer_size (buffer)); - } + write (ConstBufferSequence const& buffers); std::size_t size() const; @@ -92,8 +91,9 @@ body::body() inline body::body (body&& other) + : buf_ (std::move(other.buf_)) { - buf_ = std::move(other.buf_); + other.clear(); } inline @@ -101,9 +101,17 @@ body& body::operator= (body&& other) { buf_ = std::move(other.buf_); + other.clear(); return *this; } +template +void +body::clear() +{ + buf_ = std::make_unique (); +} + inline void 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))); } +template +void +body::write (ConstBufferSequence const& buffers) +{ + for (auto const& buffer : buffers) + write (boost::asio::buffer_cast (buffer), + boost::asio::buffer_size (buffer)); +} + inline std::size_t body::size() const diff --git a/src/beast/beast/http/message.h b/src/beast/beast/http/message.h index 9f0ec6a66..66f398784 100644 --- a/src/beast/beast/http/message.h +++ b/src/beast/beast/http/message.h @@ -21,7 +21,6 @@ #define BEAST_HTTP_MESSAGE_H_INCLUDED #include -#include #include #include #include @@ -72,9 +71,8 @@ public: #endif - // Memberspaces + // Memberspace beast::http::headers headers; - beast::http::body body; bool request() const @@ -213,7 +211,6 @@ message::message (message&& other) , keep_alive_ (other.keep_alive_) , upgrade_ (other.upgrade_) , headers (std::move(other.headers)) - , body (std::move(other.body)) { } @@ -230,33 +227,32 @@ message::operator= (message&& other) keep_alive_ = other.keep_alive_; upgrade_ = other.upgrade_; headers = std::move(other.headers); - body = std::move(other.body); return *this; } #endif //------------------------------------------------------------------------------ -template +template void -write (AsioStreamBuf& stream, std::string const& s) +write (Streambuf& stream, std::string const& s) { stream.commit (boost::asio::buffer_copy ( stream.prepare (s.size()), boost::asio::buffer(s))); } -template +template void -write (AsioStreamBuf& stream, char const* s) +write (Streambuf& stream, char const* s) { auto const len (::strlen(s)); stream.commit (boost::asio::buffer_copy ( stream.prepare (len), boost::asio::buffer (s, len))); } -template +template void -write (AsioStreamBuf& stream, message const& m) +write (Streambuf& stream, message const& m) { if (m.request()) { @@ -311,4 +307,4 @@ to_string (message const& m) } // http } // beast -#endif \ No newline at end of file +#endif diff --git a/src/beast/beast/http/parser.h b/src/beast/beast/http/parser.h index 769f73d92..8d0e8ad81 100644 --- a/src/beast/beast/http/parser.h +++ b/src/beast/beast/http/parser.h @@ -21,6 +21,8 @@ #define BEAST_HTTP_PARSER_H_INCLUDED #include +#include +#include #include #include @@ -34,15 +36,33 @@ class parser : public beast::http::basic_parser { private: std::reference_wrapper message_; + std::function write_body_; public: /** 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 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) , message_(m) { + write_body_ = [&b](void const* data, std::size_t size) + { + b.write(data, size); + }; + message_.get().request(request); } @@ -135,7 +155,7 @@ parser::operator= (parser&& other) template void -parser::do_start () +parser::do_start() { } @@ -176,7 +196,7 @@ template void parser::do_body (void const* data, std::size_t bytes) { - message_.get().body.write (data, bytes); + write_body_(data, bytes); } template diff --git a/src/beast/beast/http/tests/parser.test.cpp b/src/beast/beast/http/tests/parser.test.cpp index d81946383..c8e8ace4f 100644 --- a/src/beast/beast/http/tests/parser.test.cpp +++ b/src/beast/beast/http/tests/parser.test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace beast { namespace http { @@ -31,7 +32,8 @@ public: request (std::string const& text) { message m; - parser p (m, true); + body b; + parser p (m, b, true); auto result (p.write (boost::asio::buffer(text))); p.write_eof(); return std::make_pair (std::move(m), result.first); @@ -65,7 +67,8 @@ public: "\r\n" ; message m; - parser p (m, true); + body b; + parser p (m, b, true); auto result (p.write (boost::asio::buffer(text))); expect (! result.first); auto result2 (p.write_eof()); @@ -80,7 +83,8 @@ public: "\r\n" ; message m; - parser p (m, true); + body b; + parser p (m, b, true); auto result = p.write (boost::asio::buffer(text)); if (expect (result.first)) expect (result.first.message() == "invalid HTTP method"); diff --git a/src/ripple/app/main/ServerHandlerImp.cpp b/src/ripple/app/main/ServerHandlerImp.cpp index 89a6f4191..2ca7232f9 100644 --- a/src/ripple/app/main/ServerHandlerImp.cpp +++ b/src/ripple/app/main/ServerHandlerImp.cpp @@ -113,7 +113,7 @@ void ServerHandlerImp::onRequest (HTTP::Session& session) { // Check user/password authorization - auto const headers (build_map (session.message().headers)); + auto const headers = build_map (session.request().headers); if (! HTTPAuthorized (headers)) { session.write (HTTPReply (403, "Forbidden")); @@ -146,11 +146,10 @@ ServerHandlerImp::onStopped (HTTP::Server&) void ServerHandlerImp::processSession (Job& job, HTTP::Session& session) { - auto const s (to_string(session.message().body)); - session.write (processRequest (to_string(session.message().body), + session.write (processRequest (to_string(session.body()), session.remoteAddress().at_port(0))); - if (session.message().keep_alive()) + if (session.request().keep_alive()) { session.complete(); } diff --git a/src/ripple/http/Session.h b/src/ripple/http/Session.h index 17f671322..7889b7d3c 100644 --- a/src/ripple/http/Session.h +++ b/src/ripple/http/Session.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_HTTP_SESSION_H_INCLUDED #define RIPPLE_HTTP_SESSION_H_INCLUDED +#include #include #include #include @@ -59,10 +60,15 @@ public: beast::IP::Endpoint remoteAddress() = 0; - /** Returns the currently known set of headers. */ + /** Returns the current HTTP request. */ virtual beast::http::message& - message() = 0; + request() = 0; + + /** Returns the Content-Body of the current HTTP request. */ + virtual + beast::http::body const& + body() = 0; /** Send a copy of data asynchronously. */ /** @{ */ diff --git a/src/ripple/http/impl/Peer.h b/src/ripple/http/impl/Peer.h index fcaf68509..112a0229c 100644 --- a/src/ripple/http/impl/Peer.h +++ b/src/ripple/http/impl/Peer.h @@ -103,6 +103,7 @@ protected: boost::asio::streambuf read_buf_; beast::http::message message_; + beast::http::body body_; std::list write_queue_; std::mutex mutex_; bool graceful_ = false; @@ -181,11 +182,17 @@ protected: } beast::http::message& - message() override + request() override { return message_; } + beast::http::body const& + body() override + { + return body_; + } + void write (void const* buffer, std::size_t bytes) override; @@ -481,7 +488,8 @@ Peer::do_read (boost::asio::yield_context yield) error_code ec; bool eof = false; - beast::http::parser parser (message_, true); + body_.clear(); + beast::http::parser parser (message_, body_, true); for(;;) { if (read_buf_.size() == 0) diff --git a/src/ripple/http/tests/Server.test.cpp b/src/ripple/http/tests/Server.test.cpp index 62deafdb9..ff90feb80 100644 --- a/src/ripple/http/tests/Server.test.cpp +++ b/src/ripple/http/tests/Server.test.cpp @@ -66,7 +66,7 @@ public: onRequest (Session& session) override { session.write (std::string ("Hello, world!\n")); - if (session.message().keep_alive()) + if (session.request().keep_alive()) session.complete(); else session.close (true); diff --git a/src/ripple/overlay/impl/PeerImp.cpp b/src/ripple/overlay/impl/PeerImp.cpp index 01b73e92f..3af6d4049 100644 --- a/src/ripple/overlay/impl/PeerImp.cpp +++ b/src/ripple/overlay/impl/PeerImp.cpp @@ -413,7 +413,9 @@ PeerImp::on_write_http_request (error_code ec, std::size_t bytes_transferred) { // done sending request, now read the response http_message_ = boost::in_place (); - http_parser_ = boost::in_place (std::ref(*http_message_), false); + http_body_.clear(); + http_parser_ = boost::in_place (std::ref(*http_message_), + std::ref(http_body_), false); on_read_http_response (error_code(), 0); return; } @@ -559,7 +561,9 @@ PeerImp::on_read_http_detect (error_code ec, std::size_t bytes_transferred) else if (! is_peer_protocol) { http_message_ = boost::in_place (); - http_parser_ = boost::in_place (std::ref(*http_message_), true); + http_body_.clear(); + http_parser_ = boost::in_place (std::ref(*http_message_), + std::ref(http_body_), true); on_read_http_request (error_code(), 0); return; } diff --git a/src/ripple/overlay/impl/PeerImp.h b/src/ripple/overlay/impl/PeerImp.h index 1846a27b5..918aa0cad 100644 --- a/src/ripple/overlay/impl/PeerImp.h +++ b/src/ripple/overlay/impl/PeerImp.h @@ -173,6 +173,7 @@ private: beast::asio::streambuf read_buffer_; boost::optional http_message_; boost::optional http_parser_; + beast::http::body http_body_; message_stream message_stream_; beast::asio::streambuf write_buffer_;