basic_dynamic_body.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. //
  2. // Copyright (c) 2016-2017 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_BASIC_DYNAMIC_BODY_HPP
  10. #define BOOST_BEAST_HTTP_BASIC_DYNAMIC_BODY_HPP
  11. #include <boost/beast/core/detail/config.hpp>
  12. #include <boost/beast/core/type_traits.hpp>
  13. #include <boost/beast/http/error.hpp>
  14. #include <boost/beast/http/message.hpp>
  15. #include <boost/optional.hpp>
  16. #include <algorithm>
  17. #include <cstdint>
  18. #include <utility>
  19. namespace boost {
  20. namespace beast {
  21. namespace http {
  22. /** A @b Body using a @b DynamicBuffer
  23. This body uses a @b DynamicBuffer as a memory-based container
  24. for holding message payloads. Messages using this body type
  25. may be serialized and parsed.
  26. */
  27. template<class DynamicBuffer>
  28. struct basic_dynamic_body
  29. {
  30. static_assert(
  31. boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
  32. "DynamicBuffer requirements not met");
  33. /** The type of container used for the body
  34. This determines the type of @ref message::body
  35. when this body type is used with a message container.
  36. */
  37. using value_type = DynamicBuffer;
  38. /** Returns the payload size of the body
  39. When this body is used with @ref message::prepare_payload,
  40. the Content-Length will be set to the payload size, and
  41. any chunked Transfer-Encoding will be removed.
  42. */
  43. static
  44. std::uint64_t
  45. size(value_type const& v)
  46. {
  47. return v.size();
  48. }
  49. /** The algorithm for parsing the body
  50. Meets the requirements of @b BodyReader.
  51. */
  52. #if BOOST_BEAST_DOXYGEN
  53. using reader = implementation_defined;
  54. #else
  55. class reader
  56. {
  57. value_type& body_;
  58. public:
  59. template<bool isRequest, class Fields>
  60. explicit
  61. reader(header<isRequest, Fields>&, value_type& b)
  62. : body_(b)
  63. {
  64. }
  65. void
  66. init(boost::optional<
  67. std::uint64_t> const&, error_code& ec)
  68. {
  69. ec.assign(0, ec.category());
  70. }
  71. template<class ConstBufferSequence>
  72. std::size_t
  73. put(ConstBufferSequence const& buffers,
  74. error_code& ec)
  75. {
  76. using boost::asio::buffer_copy;
  77. using boost::asio::buffer_size;
  78. auto const n = buffer_size(buffers);
  79. if(body_.size() > body_.max_size() - n)
  80. {
  81. ec = error::buffer_overflow;
  82. return 0;
  83. }
  84. boost::optional<typename
  85. DynamicBuffer::mutable_buffers_type> b;
  86. try
  87. {
  88. b.emplace(body_.prepare((std::min)(n,
  89. body_.max_size() - body_.size())));
  90. }
  91. catch(std::length_error const&)
  92. {
  93. ec = error::buffer_overflow;
  94. return 0;
  95. }
  96. ec.assign(0, ec.category());
  97. auto const bytes_transferred =
  98. buffer_copy(*b, buffers);
  99. body_.commit(bytes_transferred);
  100. return bytes_transferred;
  101. }
  102. void
  103. finish(error_code& ec)
  104. {
  105. ec.assign(0, ec.category());
  106. }
  107. };
  108. #endif
  109. /** The algorithm for serializing the body
  110. Meets the requirements of @b BodyWriter.
  111. */
  112. #if BOOST_BEAST_DOXYGEN
  113. using writer = implementation_defined;
  114. #else
  115. class writer
  116. {
  117. DynamicBuffer const& body_;
  118. public:
  119. using const_buffers_type =
  120. typename DynamicBuffer::const_buffers_type;
  121. template<bool isRequest, class Fields>
  122. explicit
  123. writer(header<isRequest, Fields> const&, value_type const& b)
  124. : body_(b)
  125. {
  126. }
  127. void
  128. init(error_code& ec)
  129. {
  130. ec.assign(0, ec.category());
  131. }
  132. boost::optional<std::pair<const_buffers_type, bool>>
  133. get(error_code& ec)
  134. {
  135. ec.assign(0, ec.category());
  136. return {{body_.data(), false}};
  137. }
  138. };
  139. #endif
  140. };
  141. } // http
  142. } // beast
  143. } // boost
  144. #endif