message.hpp 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. //
  2. // Copyright (c) 2016-2017 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. #ifndef BOOST_BEAST_HTTP_MESSAGE_HPP
  10. #define BOOST_BEAST_HTTP_MESSAGE_HPP
  11. #include <boost/beast/core/detail/config.hpp>
  12. #include <boost/beast/http/fields.hpp>
  13. #include <boost/beast/http/verb.hpp>
  14. #include <boost/beast/http/status.hpp>
  15. #include <boost/beast/http/type_traits.hpp>
  16. #include <boost/beast/core/string.hpp>
  17. #include <boost/beast/core/detail/empty_base_optimization.hpp>
  18. #include <boost/beast/core/detail/integer_sequence.hpp>
  19. #include <boost/assert.hpp>
  20. #include <boost/optional.hpp>
  21. #include <boost/throw_exception.hpp>
  22. #include <memory>
  23. #include <stdexcept>
  24. #include <string>
  25. #include <tuple>
  26. #include <utility>
  27. namespace boost {
  28. namespace beast {
  29. namespace http {
  30. /** A container for an HTTP request or response header.
  31. This container is derived from the `Fields` template type.
  32. To understand all of the members of this class it is necessary
  33. to view the declaration for the `Fields` type. When using
  34. the default fields container, those declarations are in
  35. @ref fields.
  36. Newly constructed header objects have version set to
  37. HTTP/1.1. Newly constructed response objects also have
  38. result code set to @ref status::ok.
  39. A `header` includes the start-line and header-fields.
  40. */
  41. #if BOOST_BEAST_DOXYGEN
  42. template<bool isRequest, class Fields = fields>
  43. struct header : Fields
  44. #else
  45. template<bool isRequest, class Fields = fields>
  46. struct header;
  47. template<class Fields>
  48. struct header<true, Fields> : Fields
  49. #endif
  50. {
  51. static_assert(is_fields<Fields>::value,
  52. "Fields requirements not met");
  53. /// Indicates if the header is a request or response.
  54. #if BOOST_BEAST_DOXYGEN
  55. using is_request = std::integral_constant<bool, isRequest>;
  56. #else
  57. using is_request = std::true_type;
  58. #endif
  59. /// The type representing the fields.
  60. using fields_type = Fields;
  61. /// Constructor
  62. header() = default;
  63. /// Constructor
  64. header(header&&) = default;
  65. /// Constructor
  66. header(header const&) = default;
  67. /// Assignment
  68. header& operator=(header&&) = default;
  69. /// Assignment
  70. header& operator=(header const&) = default;
  71. /** Return the HTTP-version.
  72. This holds both the major and minor version numbers,
  73. using these formulas:
  74. @code
  75. unsigned major = version / 10;
  76. unsigned minor = version % 10;
  77. @endcode
  78. Newly constructed headers will use HTTP/1.1 by default.
  79. */
  80. unsigned version() const noexcept
  81. {
  82. return version_;
  83. }
  84. /** Set the HTTP-version.
  85. This holds both the major and minor version numbers,
  86. using these formulas:
  87. @code
  88. unsigned major = version / 10;
  89. unsigned minor = version % 10;
  90. @endcode
  91. Newly constructed headers will use HTTP/1.1 by default.
  92. @param value The version number to use
  93. */
  94. void version(unsigned value) noexcept
  95. {
  96. BOOST_ASSERT(value > 0 && value < 100);
  97. version_ = value;
  98. }
  99. /** Return the request-method verb.
  100. If the request-method is not one of the recognized verbs,
  101. @ref verb::unknown is returned. Callers may use @ref method_string
  102. to retrieve the exact text.
  103. @note This function is only available when `isRequest == true`.
  104. @see @ref method_string
  105. */
  106. verb
  107. method() const;
  108. /** Set the request-method.
  109. This function will set the method for requests to a known verb.
  110. @param v The request method verb to set.
  111. This may not be @ref verb::unknown.
  112. @throws std::invalid_argument when `v == verb::unknown`.
  113. @note This function is only available when `isRequest == true`.
  114. */
  115. void
  116. method(verb v);
  117. /** Return the request-method as a string.
  118. @note This function is only available when `isRequest == true`.
  119. @see @ref method
  120. */
  121. string_view
  122. method_string() const;
  123. /** Set the request-method.
  124. This function will set the request-method a known verb
  125. if the string matches, otherwise it will store a copy of
  126. the passed string.
  127. @param s A string representing the request-method.
  128. @note This function is only available when `isRequest == true`.
  129. */
  130. void
  131. method_string(string_view s);
  132. /** Returns the request-target string.
  133. The request target string returned is the same string which
  134. was received from the network or stored. In particular, it will
  135. contain url-encoded characters and should follow the syntax
  136. rules for URIs used with HTTP.
  137. @note This function is only available when `isRequest == true`.
  138. */
  139. string_view
  140. target() const;
  141. /** Set the request-target string.
  142. It is the caller's responsibility to ensure that the request
  143. target string follows the syntax rules for URIs used with
  144. HTTP. In particular, reserved or special characters must be
  145. url-encoded. The implementation does not perform syntax checking
  146. on the passed string.
  147. @param s A string representing the request-target.
  148. @note This function is only available when `isRequest == true`.
  149. */
  150. void
  151. target(string_view s);
  152. // VFALCO Don't rearrange these declarations or
  153. // ifdefs, or else the documentation will break.
  154. /** Constructor
  155. @param args Arguments forwarded to the `Fields`
  156. base class constructor.
  157. @note This constructor participates in overload
  158. resolution if and only if the first parameter is
  159. not convertible to @ref header, @ref verb, or
  160. @ref status.
  161. */
  162. #if BOOST_BEAST_DOXYGEN
  163. template<class... Args>
  164. explicit
  165. header(Args&&... args);
  166. #else
  167. template<class Arg1, class... ArgN,
  168. class = typename std::enable_if<
  169. ! std::is_convertible<typename
  170. std::decay<Arg1>::type, header>::value &&
  171. ! std::is_convertible<typename
  172. std::decay<Arg1>::type, verb>::value &&
  173. ! std::is_convertible<typename
  174. std::decay<Arg1>::type, header>::value
  175. >::type>
  176. explicit
  177. header(Arg1&& arg1, ArgN&&... argn);
  178. private:
  179. template<bool, class, class>
  180. friend struct message;
  181. template<class T>
  182. friend
  183. void
  184. swap(header<true, T>& m1, header<true, T>& m2);
  185. template<class... FieldsArgs>
  186. header(
  187. verb method,
  188. string_view target_,
  189. unsigned version_value,
  190. FieldsArgs&&... fields_args)
  191. : Fields(std::forward<FieldsArgs>(fields_args)...)
  192. , method_(method)
  193. {
  194. version(version_value);
  195. target(target_);
  196. }
  197. unsigned version_ = 11;
  198. verb method_ = verb::unknown;
  199. };
  200. /** A container for an HTTP request or response header.
  201. A `header` includes the start-line and header-fields.
  202. */
  203. template<class Fields>
  204. struct header<false, Fields> : Fields
  205. {
  206. static_assert(is_fields<Fields>::value,
  207. "Fields requirements not met");
  208. /// Indicates if the header is a request or response.
  209. using is_request = std::false_type;
  210. /// The type representing the fields.
  211. using fields_type = Fields;
  212. /// Constructor.
  213. header() = default;
  214. /// Constructor
  215. header(header&&) = default;
  216. /// Constructor
  217. header(header const&) = default;
  218. /// Assignment
  219. header& operator=(header&&) = default;
  220. /// Assignment
  221. header& operator=(header const&) = default;
  222. /** Constructor
  223. @param args Arguments forwarded to the `Fields`
  224. base class constructor.
  225. @note This constructor participates in overload
  226. resolution if and only if the first parameter is
  227. not convertible to @ref header, @ref verb, or
  228. @ref status.
  229. */
  230. template<class Arg1, class... ArgN,
  231. class = typename std::enable_if<
  232. ! std::is_convertible<typename
  233. std::decay<Arg1>::type, status>::value &&
  234. ! std::is_convertible<typename
  235. std::decay<Arg1>::type, header>::value
  236. >::type>
  237. explicit
  238. header(Arg1&& arg1, ArgN&&... argn);
  239. /** Return the HTTP-version.
  240. This holds both the major and minor version numbers,
  241. using these formulas:
  242. @code
  243. unsigned major = version / 10;
  244. unsigned minor = version % 10;
  245. @endcode
  246. Newly constructed headers will use HTTP/1.1 by default.
  247. */
  248. unsigned version() const noexcept
  249. {
  250. return version_;
  251. }
  252. /** Set the HTTP-version.
  253. This holds both the major and minor version numbers,
  254. using these formulas:
  255. @code
  256. unsigned major = version / 10;
  257. unsigned minor = version % 10;
  258. @endcode
  259. Newly constructed headers will use HTTP/1.1 by default.
  260. @param value The version number to use
  261. */
  262. void version(unsigned value) noexcept
  263. {
  264. BOOST_ASSERT(value > 0 && value < 100);
  265. version_ = value;
  266. }
  267. #endif
  268. /** The response status-code result.
  269. If the actual status code is not a known code, this
  270. function returns @ref status::unknown. Use @ref result_int
  271. to return the raw status code as a number.
  272. @note This member is only available when `isRequest == false`.
  273. */
  274. status
  275. result() const;
  276. /** Set the response status-code.
  277. @param v The code to set.
  278. @note This member is only available when `isRequest == false`.
  279. */
  280. void
  281. result(status v);
  282. /** Set the response status-code as an integer.
  283. This sets the status code to the exact number passed in.
  284. If the number does not correspond to one of the known
  285. status codes, the function @ref result will return
  286. @ref status::unknown. Use @ref result_int to obtain the
  287. original raw status-code.
  288. @param v The status-code integer to set.
  289. @throws std::invalid_argument if `v > 999`.
  290. */
  291. void
  292. result(unsigned v);
  293. /** The response status-code expressed as an integer.
  294. This returns the raw status code as an integer, even
  295. when that code is not in the list of known status codes.
  296. @note This member is only available when `isRequest == false`.
  297. */
  298. unsigned
  299. result_int() const;
  300. /** Return the response reason-phrase.
  301. The reason-phrase is obsolete as of rfc7230.
  302. @note This function is only available when `isRequest == false`.
  303. */
  304. string_view
  305. reason() const;
  306. /** Set the response reason-phrase (deprecated)
  307. This function sets a custom reason-phrase to a copy of
  308. the string passed in. Normally it is not necessary to set
  309. the reason phrase on an outgoing response object; the
  310. implementation will automatically use the standard reason
  311. text for the corresponding status code.
  312. To clear a previously set custom phrase, pass an empty
  313. string. This will restore the default standard reason text
  314. based on the status code used when serializing.
  315. The reason-phrase is obsolete as of rfc7230.
  316. @param s The string to use for the reason-phrase.
  317. @note This function is only available when `isRequest == false`.
  318. */
  319. void
  320. reason(string_view s);
  321. private:
  322. #if ! BOOST_BEAST_DOXYGEN
  323. template<bool, class, class>
  324. friend struct message;
  325. template<class T>
  326. friend
  327. void
  328. swap(header<false, T>& m1, header<false, T>& m2);
  329. template<class... FieldsArgs>
  330. header(
  331. status result,
  332. unsigned version_value,
  333. FieldsArgs&&... fields_args)
  334. : Fields(std::forward<FieldsArgs>(fields_args)...)
  335. , result_(result)
  336. {
  337. version(version_value);
  338. }
  339. unsigned version_ = 11;
  340. status result_ = status::ok;
  341. #endif
  342. };
  343. /// A typical HTTP request header
  344. template<class Fields = fields>
  345. using request_header = header<true, Fields>;
  346. /// A typical HTTP response header
  347. template<class Fields = fields>
  348. using response_header = header<false, Fields>;
  349. #if defined(BOOST_MSVC)
  350. // Workaround for MSVC bug with private base classes
  351. namespace detail {
  352. template<class T>
  353. using value_type_t = typename T::value_type;
  354. } // detail
  355. #endif
  356. /** A container for a complete HTTP message.
  357. This container is derived from the `Fields` template type.
  358. To understand all of the members of this class it is necessary
  359. to view the declaration for the `Fields` type. When using
  360. the default fields container, those declarations are in
  361. @ref fields.
  362. A message can be a request or response, depending on the
  363. `isRequest` template argument value. Requests and responses
  364. have different types; functions may be overloaded based on
  365. the type if desired.
  366. The `Body` template argument type determines the model used
  367. to read or write the content body of the message.
  368. Newly constructed messages objects have version set to
  369. HTTP/1.1. Newly constructed response objects also have
  370. result code set to @ref status::ok.
  371. @tparam isRequest `true` if this represents a request,
  372. or `false` if this represents a response. Some class data
  373. members are conditionally present depending on this value.
  374. @tparam Body A type meeting the requirements of Body.
  375. @tparam Fields The type of container used to hold the
  376. field value pairs.
  377. */
  378. template<bool isRequest, class Body, class Fields = fields>
  379. struct message
  380. : header<isRequest, Fields>
  381. #if ! BOOST_BEAST_DOXYGEN
  382. , beast::detail::empty_base_optimization<
  383. typename Body::value_type>
  384. #endif
  385. {
  386. /// The base class used to hold the header portion of the message.
  387. using header_type = header<isRequest, Fields>;
  388. /** The type providing the body traits.
  389. The @ref message::body member will be of type `body_type::value_type`.
  390. */
  391. using body_type = Body;
  392. /// Constructor
  393. message() = default;
  394. /// Constructor
  395. message(message&&) = default;
  396. /// Constructor
  397. message(message const&) = default;
  398. /// Assignment
  399. message& operator=(message&&) = default;
  400. /// Assignment
  401. message& operator=(message const&) = default;
  402. /** Constructor
  403. @param h The header to move construct from.
  404. @param body_args Optional arguments forwarded
  405. to the `body` constructor.
  406. */
  407. template<class... BodyArgs>
  408. explicit
  409. message(header_type&& h, BodyArgs&&... body_args);
  410. /** Constructor.
  411. @param h The header to copy construct from.
  412. @param body_args Optional arguments forwarded
  413. to the `body` constructor.
  414. */
  415. template<class... BodyArgs>
  416. explicit
  417. message(header_type const& h, BodyArgs&&... body_args);
  418. /** Constructor
  419. @param method The request-method to use
  420. @param target The request-target.
  421. @param version The HTTP-version
  422. @note This function is only available when `isRequest == true`.
  423. */
  424. #if BOOST_BEAST_DOXYGEN
  425. message(verb method, string_view target, unsigned version);
  426. #else
  427. template<class Version,
  428. class = typename std::enable_if<isRequest &&
  429. std::is_convertible<Version, unsigned>::value>::type>
  430. message(verb method, string_view target, Version version);
  431. #endif
  432. /** Constructor
  433. @param method The request-method to use
  434. @param target The request-target.
  435. @param version The HTTP-version
  436. @param body_arg An argument forwarded to the `body` constructor.
  437. @note This function is only available when `isRequest == true`.
  438. */
  439. #if BOOST_BEAST_DOXYGEN
  440. template<class BodyArg>
  441. message(verb method, string_view target,
  442. unsigned version, BodyArg&& body_arg);
  443. #else
  444. template<class Version, class BodyArg,
  445. class = typename std::enable_if<isRequest &&
  446. std::is_convertible<Version, unsigned>::value>::type>
  447. message(verb method, string_view target,
  448. Version version, BodyArg&& body_arg);
  449. #endif
  450. /** Constructor
  451. @param method The request-method to use
  452. @param target The request-target.
  453. @param version The HTTP-version
  454. @param body_arg An argument forwarded to the `body` constructor.
  455. @param fields_arg An argument forwarded to the `Fields` constructor.
  456. @note This function is only available when `isRequest == true`.
  457. */
  458. #if BOOST_BEAST_DOXYGEN
  459. template<class BodyArg, class FieldsArg>
  460. message(verb method, string_view target, unsigned version,
  461. BodyArg&& body_arg, FieldsArg&& fields_arg);
  462. #else
  463. template<class Version, class BodyArg, class FieldsArg,
  464. class = typename std::enable_if<isRequest &&
  465. std::is_convertible<Version, unsigned>::value>::type>
  466. message(verb method, string_view target, Version version,
  467. BodyArg&& body_arg, FieldsArg&& fields_arg);
  468. #endif
  469. /** Constructor
  470. @param result The status-code for the response
  471. @param version The HTTP-version
  472. @note This member is only available when `isRequest == false`.
  473. */
  474. #if BOOST_BEAST_DOXYGEN
  475. message(status result, unsigned version);
  476. #else
  477. template<class Version,
  478. class = typename std::enable_if<! isRequest &&
  479. std::is_convertible<Version, unsigned>::value>::type>
  480. message(status result, Version version);
  481. #endif
  482. /** Constructor
  483. @param result The status-code for the response
  484. @param version The HTTP-version
  485. @param body_arg An argument forwarded to the `body` constructor.
  486. @note This member is only available when `isRequest == false`.
  487. */
  488. #if BOOST_BEAST_DOXYGEN
  489. template<class BodyArg>
  490. message(status result, unsigned version, BodyArg&& body_arg);
  491. #else
  492. template<class Version, class BodyArg,
  493. class = typename std::enable_if<! isRequest &&
  494. std::is_convertible<Version, unsigned>::value>::type>
  495. message(status result, Version version, BodyArg&& body_arg);
  496. #endif
  497. /** Constructor
  498. @param result The status-code for the response
  499. @param version The HTTP-version
  500. @param body_arg An argument forwarded to the `body` constructor.
  501. @param fields_arg An argument forwarded to the `Fields` base class constructor.
  502. @note This member is only available when `isRequest == false`.
  503. */
  504. #if BOOST_BEAST_DOXYGEN
  505. template<class BodyArg, class FieldsArg>
  506. message(status result, unsigned version,
  507. BodyArg&& body_arg, FieldsArg&& fields_arg);
  508. #else
  509. template<class Version, class BodyArg, class FieldsArg,
  510. class = typename std::enable_if<! isRequest &&
  511. std::is_convertible<Version, unsigned>::value>::type>
  512. message(status result, Version version,
  513. BodyArg&& body_arg, FieldsArg&& fields_arg);
  514. #endif
  515. /** Constructor
  516. The header and body are default-constructed.
  517. */
  518. explicit
  519. message(std::piecewise_construct_t);
  520. /** Construct a message.
  521. @param body_args A tuple forwarded as a parameter
  522. pack to the body constructor.
  523. */
  524. template<class... BodyArgs>
  525. message(std::piecewise_construct_t,
  526. std::tuple<BodyArgs...> body_args);
  527. /** Construct a message.
  528. @param body_args A tuple forwarded as a parameter
  529. pack to the body constructor.
  530. @param fields_args A tuple forwarded as a parameter
  531. pack to the `Fields` constructor.
  532. */
  533. template<class... BodyArgs, class... FieldsArgs>
  534. message(std::piecewise_construct_t,
  535. std::tuple<BodyArgs...> body_args,
  536. std::tuple<FieldsArgs...> fields_args);
  537. /// Returns the header portion of the message
  538. header_type const&
  539. base() const
  540. {
  541. return *this;
  542. }
  543. /// Returns the header portion of the message
  544. header_type&
  545. base()
  546. {
  547. return *this;
  548. }
  549. /// Returns `true` if the chunked Transfer-Encoding is specified
  550. bool
  551. chunked() const
  552. {
  553. return this->get_chunked_impl();
  554. }
  555. /** Set or clear the chunked Transfer-Encoding
  556. This function will set or removed the "chunked" transfer
  557. encoding as the last item in the list of encodings in the
  558. field.
  559. If the result of removing the chunked token results in an
  560. empty string, the field is erased.
  561. The Content-Length field is erased unconditionally.
  562. */
  563. void
  564. chunked(bool value);
  565. /** Returns `true` if the Content-Length field is present.
  566. This function inspects the fields and returns `true` if
  567. the Content-Length field is present. The properties of the
  568. body are not checked, this only looks for the field.
  569. */
  570. bool
  571. has_content_length() const
  572. {
  573. return this->has_content_length_impl();
  574. }
  575. /** Set or clear the Content-Length field
  576. This function adjusts the Content-Length field as follows:
  577. @li If `value` specifies a value, the Content-Length field
  578. is set to the value. Otherwise
  579. @li The Content-Length field is erased.
  580. If "chunked" token appears as the last item in the
  581. Transfer-Encoding field it is unconditionally removed.
  582. @param value The value to set for Content-Length.
  583. */
  584. void
  585. content_length(boost::optional<std::uint64_t> const& value);
  586. /** Returns `true` if the message semantics indicate keep-alive
  587. The value depends on the version in the message, which must
  588. be set to the final value before this function is called or
  589. else the return value is unreliable.
  590. */
  591. bool
  592. keep_alive() const
  593. {
  594. return this->get_keep_alive_impl(this->version());
  595. }
  596. /** Set the keep-alive message semantic option
  597. This function adjusts the Connection field to indicate
  598. whether or not the connection should be kept open after
  599. the corresponding response. The result depends on the
  600. version set on the message, which must be set to the
  601. final value before making this call.
  602. @param value `true` if the connection should persist.
  603. */
  604. void
  605. keep_alive(bool value)
  606. {
  607. this->set_keep_alive_impl(this->version(), value);
  608. }
  609. /** Returns `true` if the message semantics require an end of file.
  610. For HTTP requests, this function returns the logical
  611. NOT of a call to @ref keep_alive.
  612. For HTTP responses, this function returns the logical NOT
  613. of a call to @ref keep_alive if any of the following are true:
  614. @li @ref has_content_length would return `true`
  615. @li @ref chunked would return `true`
  616. @li @ref result returns @ref status::no_content
  617. @li @ref result returns @ref status::not_modified
  618. @li @ref result returns any informational status class (100 to 199)
  619. Otherwise, the function returns `true`.
  620. @see https://tools.ietf.org/html/rfc7230#section-3.3
  621. */
  622. bool
  623. need_eof() const
  624. {
  625. return need_eof(typename header_type::is_request{});
  626. }
  627. /** Returns the payload size of the body in octets if possible.
  628. This function invokes the @b Body algorithm to measure
  629. the number of octets in the serialized body container. If
  630. there is no body, this will return zero. Otherwise, if the
  631. body exists but is not known ahead of time, `boost::none`
  632. is returned (usually indicating that a chunked Transfer-Encoding
  633. will be used).
  634. @note The value of the Content-Length field in the message
  635. is not inspected.
  636. */
  637. boost::optional<std::uint64_t>
  638. payload_size() const;
  639. /** Prepare the message payload fields for the body.
  640. This function will adjust the Content-Length and
  641. Transfer-Encoding field values based on the properties
  642. of the body.
  643. @par Example
  644. @code
  645. request<string_body> req{verb::post, "/"};
  646. req.set(field::user_agent, "Beast");
  647. req.body() = "Hello, world!";
  648. req.prepare_payload();
  649. @endcode
  650. */
  651. void
  652. prepare_payload()
  653. {
  654. prepare_payload(typename header_type::is_request{});
  655. }
  656. /// Returns the body
  657. #if BOOST_BEAST_DOXYGEN || ! defined(BOOST_MSVC)
  658. typename body_type::value_type&
  659. #else
  660. detail::value_type_t<Body>&
  661. #endif
  662. body()& noexcept
  663. {
  664. return this->beast::detail::empty_base_optimization<
  665. typename Body::value_type>::member();
  666. }
  667. /// Returns the body
  668. #if BOOST_BEAST_DOXYGEN || ! defined(BOOST_MSVC)
  669. typename body_type::value_type&&
  670. #else
  671. detail::value_type_t<Body>&&
  672. #endif
  673. body()&& noexcept
  674. {
  675. return std::move(
  676. this->beast::detail::empty_base_optimization<
  677. typename Body::value_type>::member());
  678. }
  679. /// Returns the body
  680. #if BOOST_BEAST_DOXYGEN || ! defined(BOOST_MSVC)
  681. typename body_type::value_type const&
  682. #else
  683. detail::value_type_t<Body> const&
  684. #endif
  685. body() const& noexcept
  686. {
  687. return this->beast::detail::empty_base_optimization<
  688. typename Body::value_type>::member();
  689. }
  690. private:
  691. static_assert(is_body<Body>::value,
  692. "Body requirements not met");
  693. template<
  694. class... BodyArgs,
  695. std::size_t... IBodyArgs>
  696. message(
  697. std::piecewise_construct_t,
  698. std::tuple<BodyArgs...>& body_args,
  699. beast::detail::index_sequence<IBodyArgs...>)
  700. : beast::detail::empty_base_optimization<
  701. typename Body::value_type>(
  702. std::forward<BodyArgs>(
  703. std::get<IBodyArgs>(body_args))...)
  704. {
  705. boost::ignore_unused(body_args);
  706. }
  707. template<
  708. class... BodyArgs,
  709. class... FieldsArgs,
  710. std::size_t... IBodyArgs,
  711. std::size_t... IFieldsArgs>
  712. message(
  713. std::piecewise_construct_t,
  714. std::tuple<BodyArgs...>& body_args,
  715. std::tuple<FieldsArgs...>& fields_args,
  716. beast::detail::index_sequence<IBodyArgs...>,
  717. beast::detail::index_sequence<IFieldsArgs...>)
  718. : header_type(std::forward<FieldsArgs>(
  719. std::get<IFieldsArgs>(fields_args))...)
  720. , beast::detail::empty_base_optimization<
  721. typename Body::value_type>(
  722. std::forward<BodyArgs>(
  723. std::get<IBodyArgs>(body_args))...)
  724. {
  725. boost::ignore_unused(body_args);
  726. boost::ignore_unused(fields_args);
  727. }
  728. bool
  729. need_eof(std::true_type) const
  730. {
  731. return ! keep_alive();
  732. }
  733. bool
  734. need_eof(std::false_type) const;
  735. boost::optional<std::uint64_t>
  736. payload_size(std::true_type) const
  737. {
  738. return Body::size(this->body());
  739. }
  740. boost::optional<std::uint64_t>
  741. payload_size(std::false_type) const
  742. {
  743. return boost::none;
  744. }
  745. void
  746. prepare_payload(std::true_type);
  747. void
  748. prepare_payload(std::false_type);
  749. };
  750. /// A typical HTTP request
  751. template<class Body, class Fields = fields>
  752. using request = message<true, Body, Fields>;
  753. /// A typical HTTP response
  754. template<class Body, class Fields = fields>
  755. using response = message<false, Body, Fields>;
  756. //------------------------------------------------------------------------------
  757. #if BOOST_BEAST_DOXYGEN
  758. /** Swap two header objects.
  759. @par Requirements
  760. `Fields` is @b Swappable.
  761. */
  762. template<bool isRequest, class Fields>
  763. void
  764. swap(
  765. header<isRequest, Fields>& m1,
  766. header<isRequest, Fields>& m2);
  767. #endif
  768. /** Swap two message objects.
  769. @par Requirements:
  770. `Body::value_type` and `Fields` are @b Swappable.
  771. */
  772. template<bool isRequest, class Body, class Fields>
  773. void
  774. swap(
  775. message<isRequest, Body, Fields>& m1,
  776. message<isRequest, Body, Fields>& m2);
  777. } // http
  778. } // beast
  779. } // boost
  780. #include <boost/beast/http/impl/message.ipp>
  781. #endif