message.hpp 27 KB

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