1 // 2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // Official repository: https://github.com/boostorg/beast 8 // 9 10 #ifndef BOOST_BEAST_HTTP_BASIC_DYNAMIC_BODY_HPP 11 #define BOOST_BEAST_HTTP_BASIC_DYNAMIC_BODY_HPP 12 13 #include <boost/beast/core/detail/config.hpp> 14 #include <boost/beast/core/buffer_traits.hpp> 15 #include <boost/beast/core/detail/buffer.hpp> 16 #include <boost/beast/core/detail/clamp.hpp> 17 #include <boost/beast/http/error.hpp> 18 #include <boost/beast/http/message.hpp> 19 #include <boost/optional.hpp> 20 #include <algorithm> 21 #include <cstdint> 22 #include <utility> 23 24 namespace boost { 25 namespace beast { 26 namespace http { 27 28 /** A <em>Body</em> using a <em>DynamicBuffer</em> 29 30 This body uses a <em>DynamicBuffer</em> as a memory-based container 31 for holding message payloads. Messages using this body type 32 may be serialized and parsed. 33 */ 34 template<class DynamicBuffer> 35 struct basic_dynamic_body 36 { 37 static_assert( 38 net::is_dynamic_buffer<DynamicBuffer>::value, 39 "DynamicBuffer type requirements not met"); 40 41 /** The type of container used for the body 42 43 This determines the type of @ref message::body 44 when this body type is used with a message container. 45 */ 46 using value_type = DynamicBuffer; 47 48 /** Returns the payload size of the body 49 50 When this body is used with @ref message::prepare_payload, 51 the Content-Length will be set to the payload size, and 52 any chunked Transfer-Encoding will be removed. 53 */ 54 static 55 std::uint64_t sizeboost::beast::http::basic_dynamic_body56 size(value_type const& v) 57 { 58 return v.size(); 59 } 60 61 /** The algorithm for parsing the body 62 63 Meets the requirements of <em>BodyReader</em>. 64 */ 65 #if BOOST_BEAST_DOXYGEN 66 using reader = __implementation_defined__; 67 #else 68 class reader 69 { 70 value_type& body_; 71 72 public: 73 template<bool isRequest, class Fields> 74 explicit reader(header<isRequest,Fields> &,value_type & b)75 reader(header<isRequest, Fields>&, value_type& b) 76 : body_(b) 77 { 78 } 79 80 void init(boost::optional<std::uint64_t> const &,error_code & ec)81 init(boost::optional< 82 std::uint64_t> const&, error_code& ec) 83 { 84 ec = {}; 85 } 86 87 template<class ConstBufferSequence> 88 std::size_t put(ConstBufferSequence const & buffers,error_code & ec)89 put(ConstBufferSequence const& buffers, 90 error_code& ec) 91 { 92 auto const n = buffer_bytes(buffers); 93 if(beast::detail::sum_exceeds(body_.size(), n, body_.max_size())) 94 { 95 ec = error::buffer_overflow; 96 return 0; 97 } 98 auto const mb = 99 beast::detail::dynamic_buffer_prepare( 100 body_, (std::min)(n, 101 body_.max_size() - body_.size()), 102 ec, error::buffer_overflow); 103 if(ec) 104 return 0; 105 auto const bytes_transferred = 106 net::buffer_copy(*mb, buffers); 107 body_.commit(bytes_transferred); 108 return bytes_transferred; 109 } 110 111 void finish(error_code & ec)112 finish(error_code& ec) 113 { 114 ec = {}; 115 } 116 }; 117 #endif 118 119 /** The algorithm for serializing the body 120 121 Meets the requirements of <em>BodyWriter</em>. 122 */ 123 #if BOOST_BEAST_DOXYGEN 124 using writer = __implementation_defined__; 125 #else 126 class writer 127 { 128 DynamicBuffer const& body_; 129 130 public: 131 using const_buffers_type = 132 typename DynamicBuffer::const_buffers_type; 133 134 template<bool isRequest, class Fields> 135 explicit writer(header<isRequest,Fields> const &,value_type const & b)136 writer(header<isRequest, Fields> const&, value_type const& b) 137 : body_(b) 138 { 139 } 140 141 void init(error_code & ec)142 init(error_code& ec) 143 { 144 ec = {}; 145 } 146 147 boost::optional<std::pair<const_buffers_type, bool>> get(error_code & ec)148 get(error_code& ec) 149 { 150 ec = {}; 151 return {{body_.data(), false}}; 152 } 153 }; 154 #endif 155 }; 156 157 } // http 158 } // beast 159 } // boost 160 161 #endif 162