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 #include <boost/beast/core/buffer_traits.hpp> 11 #include <boost/beast/core/error.hpp> 12 #include <boost/beast/core/file_base.hpp> 13 #include <boost/beast/http/message.hpp> 14 #include <boost/beast/http/type_traits.hpp> 15 #include <boost/optional.hpp> 16 #include <cstdint> 17 #include <utility> 18 19 namespace boost { 20 namespace beast { 21 namespace http { 22 23 class BodyWriter; 24 class BodyReader; 25 26 //[concept_Body 27 28 struct Body 29 { 30 // The type of message::body when used 31 struct value_type; 32 33 /// The algorithm used during parsing 34 class reader; 35 36 /// The algorithm used during serialization 37 class writer; 38 39 /// Returns the body's payload size 40 static 41 std::uint64_t 42 size(value_type const& body); 43 }; 44 45 static_assert(is_body<Body>::value, ""); 46 47 //] 48 49 struct Body_BodyWriter { 50 struct value_type{}; 51 //[concept_BodyWriter 52 53 struct BodyWriter 54 { 55 public: 56 /// The type of buffer returned by `get`. 57 using const_buffers_type = net::const_buffer; 58 59 /** Construct the writer. 60 61 @param h The header for the message being serialized 62 63 @param body The body being serialized 64 */ 65 template<bool isRequest, class Fields> 66 BodyWriter(header<isRequest, Fields> const& h, value_type const& body); 67 68 /** Initialize the writer. 69 70 This is called after construction and before the first 71 call to `get`. The message is valid and complete upon 72 entry. 73 74 @param ec Set to the error, if any occurred. 75 */ 76 void initboost::beast::http::Body_BodyWriter::BodyWriter77 init(error_code& ec) 78 { 79 // The specification requires this to indicate "no error" 80 ec = {}; 81 } 82 83 /** Returns the next buffer in the body. 84 85 @li If the return value is `boost::none` (unseated optional) and 86 `ec` does not contain an error, this indicates the end of the 87 body, no more buffers are present. 88 89 @li If the optional contains a value, the first element of the 90 pair represents a <em>ConstBufferSequence</em> containing one or 91 more octets of the body data. The second element indicates 92 whether or not there are additional octets of body data. 93 A value of `true` means there is more data, and that the 94 implementation will perform a subsequent call to `get`. 95 A value of `false` means there is no more body data. 96 97 @li If `ec` contains an error code, the return value is ignored. 98 99 @param ec Set to the error, if any occurred. 100 */ 101 boost::optional<std::pair<const_buffers_type, bool>> getboost::beast::http::Body_BodyWriter::BodyWriter102 get(error_code& ec) 103 { 104 // The specification requires this to indicate "no error" 105 ec = {}; 106 107 return boost::none; // for exposition only 108 } 109 }; 110 111 //] 112 using writer = BodyWriter; 113 }; 114 115 static_assert(is_body_writer<Body_BodyWriter>::value, ""); 116 117 struct Body_BodyReader { 118 struct value_type{}; 119 //[concept_BodyReader 120 121 struct BodyReader 122 { 123 /** Construct the reader. 124 125 @param h The header for the message being parsed 126 127 @param body The body to store the parsed results into 128 */ 129 template<bool isRequest, class Fields> 130 BodyReader(header<isRequest, Fields>& h, value_type& body); 131 132 /** Initialize the reader. 133 134 This is called after construction and before the first 135 call to `put`. The message is valid and complete upon 136 entry. 137 138 @param ec Set to the error, if any occurred. 139 */ 140 void initboost::beast::http::Body_BodyReader::BodyReader141 init( 142 boost::optional<std::uint64_t> const& content_length, 143 error_code& ec) 144 { 145 boost::ignore_unused(content_length); 146 147 // The specification requires this to indicate "no error" 148 ec = {}; 149 } 150 151 /** Store buffers. 152 153 This is called zero or more times with parsed body octets. 154 155 @param buffers The constant buffer sequence to store. 156 157 @param ec Set to the error, if any occurred. 158 159 @return The number of bytes transferred from the input buffers. 160 */ 161 template<class ConstBufferSequence> 162 std::size_t putboost::beast::http::Body_BodyReader::BodyReader163 put(ConstBufferSequence const& buffers, error_code& ec) 164 { 165 // The specification requires this to indicate "no error" 166 ec = {}; 167 168 return buffer_bytes(buffers); 169 } 170 171 /** Called when the body is complete. 172 173 @param ec Set to the error, if any occurred. 174 */ 175 void finishboost::beast::http::Body_BodyReader::BodyReader176 finish(error_code& ec) 177 { 178 // The specification requires this to indicate "no error" 179 ec = {}; 180 } 181 }; 182 183 //] 184 using reader = BodyReader; 185 }; 186 187 static_assert(is_body_reader<Body_BodyReader>::value, ""); 188 189 //[concept_Fields 190 191 class Fields 192 { 193 public: 194 /// Constructed as needed when fields are serialized 195 struct writer; 196 197 protected: 198 /** Returns the request-method string. 199 200 @note Only called for requests. 201 */ 202 string_view 203 get_method_impl() const; 204 205 /** Returns the request-target string. 206 207 @note Only called for requests. 208 */ 209 string_view 210 get_target_impl() const; 211 212 /** Returns the response reason-phrase string. 213 214 @note Only called for responses. 215 */ 216 string_view 217 get_reason_impl() const; 218 219 /** Returns the chunked Transfer-Encoding setting 220 */ 221 bool 222 get_chunked_impl() const; 223 224 /** Returns the keep-alive setting 225 */ 226 bool 227 get_keep_alive_impl(unsigned version) const; 228 229 /** Returns `true` if the Content-Length field is present. 230 */ 231 bool 232 has_content_length_impl() const; 233 234 /** Set or clear the method string. 235 236 @note Only called for requests. 237 */ 238 void 239 set_method_impl(string_view s); 240 241 /** Set or clear the target string. 242 243 @note Only called for requests. 244 */ 245 void 246 set_target_impl(string_view s); 247 248 /** Set or clear the reason string. 249 250 @note Only called for responses. 251 */ 252 void 253 set_reason_impl(string_view s); 254 255 /** Sets or clears the chunked Transfer-Encoding value 256 */ 257 void 258 set_chunked_impl(bool value); 259 260 /** Sets or clears the Content-Length field 261 */ 262 void 263 set_content_length_impl(boost::optional<std::uint64_t>); 264 265 /** Adjusts the Connection field 266 */ 267 void 268 set_keep_alive_impl(unsigned version, bool keep_alive); 269 }; 270 271 static_assert(is_fields<Fields>::value, 272 "Fields type requirements not met"); 273 274 //] 275 276 struct Fields_FieldsWriter { 277 using Fields = Fields_FieldsWriter; 278 //[concept_FieldsWriter 279 280 struct FieldsWriter 281 { 282 // The type of buffers returned by `get` 283 struct const_buffers_type; 284 285 // Constructor for requests 286 FieldsWriter(Fields const& f, unsigned version, verb method); 287 288 // Constructor for responses 289 FieldsWriter(Fields const& f, unsigned version, unsigned status); 290 291 // Returns the serialized header buffers 292 const_buffers_type 293 get(); 294 }; 295 296 //] 297 }; 298 299 //[concept_File 300 301 struct File 302 { 303 /** Default constructor 304 305 There is no open file initially. 306 */ 307 File(); 308 309 /** Destructor 310 311 If the file is open it is first closed. 312 */ 313 ~File(); 314 315 /// Returns `true` if the file is open 316 bool 317 is_open() const; 318 319 /// Close the file if open 320 void 321 close(error_code& ec); 322 323 /// Open a file at the given path with the specified mode 324 void 325 open(char const* path, file_mode mode, error_code& ec); 326 327 /// Return the size of the open file 328 std::uint64_t 329 size(error_code& ec) const; 330 331 /// Return the current position in the open file 332 std::uint64_t 333 pos(error_code& ec) const; 334 335 /// Adjust the current position in the open file 336 void 337 seek(std::uint64_t offset, error_code& ec); 338 339 /// Read from the open file 340 std::size_t 341 read(void* buffer, std::size_t n, error_code& ec) const; 342 343 /// Write to the open file 344 std::size_t 345 write(void const* buffer, std::size_t n, error_code& ec); 346 }; 347 348 //] 349 350 } // http 351 } // beast 352 } // boost 353