• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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