string_body.hpp 4.6 KB

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