message.hpp 28 KB

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