string_body.hpp 4.6 KB

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