string_body.hpp 4.7 KB

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