• 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_STRING_BODY_HPP
11 #define BOOST_BEAST_HTTP_STRING_BODY_HPP
12 
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/buffer_traits.hpp>
15 #include <boost/beast/http/error.hpp>
16 #include <boost/beast/http/message.hpp>
17 #include <boost/beast/core/buffers_range.hpp>
18 #include <boost/beast/core/detail/clamp.hpp>
19 #include <boost/asio/buffer.hpp>
20 #include <boost/optional.hpp>
21 #include <cstdint>
22 #include <limits>
23 #include <memory>
24 #include <stdexcept>
25 #include <string>
26 #include <utility>
27 
28 namespace boost {
29 namespace beast {
30 namespace http {
31 
32 /** A <em>Body</em> using `std::basic_string`
33 
34     This body uses `std::basic_string` as a memory-based container
35     for holding message payloads. Messages using this body type
36     may be serialized and parsed.
37 */
38 template<
39     class CharT,
40     class Traits = std::char_traits<CharT>,
41     class Allocator = std::allocator<CharT>>
42 struct basic_string_body
43 {
44 private:
45     static_assert(
46         std::is_integral<CharT>::value &&
47             sizeof(CharT) == 1,
48         "CharT requirements not met");
49 
50 public:
51     /** The type of container used for the body
52 
53         This determines the type of @ref message::body
54         when this body type is used with a message container.
55     */
56     using value_type =
57         std::basic_string<CharT, Traits, Allocator>;
58 
59     /** Returns the payload size of the body
60 
61         When this body is used with @ref message::prepare_payload,
62         the Content-Length will be set to the payload size, and
63         any chunked Transfer-Encoding will be removed.
64     */
65     static
66     std::uint64_t
sizeboost::beast::http::basic_string_body67     size(value_type const& body)
68     {
69         return body.size();
70     }
71 
72     /** The algorithm for parsing the body
73 
74         Meets the requirements of <em>BodyReader</em>.
75     */
76 #if BOOST_BEAST_DOXYGEN
77     using reader = __implementation_defined__;
78 #else
79     class reader
80     {
81         value_type& body_;
82 
83     public:
84         template<bool isRequest, class Fields>
85         explicit
reader(header<isRequest,Fields> &,value_type & b)86         reader(header<isRequest, Fields>&, value_type& b)
87             : body_(b)
88         {
89         }
90 
91         void
init(boost::optional<std::uint64_t> const & length,error_code & ec)92         init(boost::optional<
93             std::uint64_t> const& length, error_code& ec)
94         {
95             if(length)
96             {
97                 if(*length > body_.max_size())
98                 {
99                     ec = error::buffer_overflow;
100                     return;
101                 }
102                 body_.reserve(beast::detail::clamp(*length));
103             }
104             ec = {};
105         }
106 
107         template<class ConstBufferSequence>
108         std::size_t
put(ConstBufferSequence const & buffers,error_code & ec)109         put(ConstBufferSequence const& buffers,
110             error_code& ec)
111         {
112             auto const extra = buffer_bytes(buffers);
113             auto const size = body_.size();
114             if (extra > body_.max_size() - size)
115             {
116                 ec = error::buffer_overflow;
117                 return 0;
118             }
119 
120             body_.resize(size + extra);
121             ec = {};
122             CharT* dest = &body_[size];
123             for(auto b : beast::buffers_range_ref(buffers))
124             {
125                 Traits::copy(dest, static_cast<
126                     CharT const*>(b.data()), b.size());
127                 dest += b.size();
128             }
129             return extra;
130         }
131 
132         void
finish(error_code & ec)133         finish(error_code& ec)
134         {
135             ec = {};
136         }
137     };
138 #endif
139 
140     /** The algorithm for serializing the body
141 
142         Meets the requirements of <em>BodyWriter</em>.
143     */
144 #if BOOST_BEAST_DOXYGEN
145     using writer = __implementation_defined__;
146 #else
147     class writer
148     {
149         value_type const& body_;
150 
151     public:
152         using const_buffers_type =
153             net::const_buffer;
154 
155         template<bool isRequest, class Fields>
156         explicit
writer(header<isRequest,Fields> const &,value_type const & b)157         writer(header<isRequest, Fields> const&, value_type const& b)
158             : body_(b)
159         {
160         }
161 
162         void
init(error_code & ec)163         init(error_code& ec)
164         {
165             ec = {};
166         }
167 
168         boost::optional<std::pair<const_buffers_type, bool>>
get(error_code & ec)169         get(error_code& ec)
170         {
171             ec = {};
172             return {{const_buffers_type{
173                 body_.data(), body_.size()}, false}};
174         }
175     };
176 #endif
177 };
178 
179 /// A <em>Body</em> using `std::string`
180 using string_body = basic_string_body<char>;
181 
182 } // http
183 } // beast
184 } // boost
185 
186 #endif
187