serializer.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  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_SERIALIZER_HPP
  10. #define BOOST_BEAST_HTTP_SERIALIZER_HPP
  11. #include <boost/beast/core/detail/config.hpp>
  12. #include <boost/beast/core/buffers_cat.hpp>
  13. #include <boost/beast/core/buffers_prefix.hpp>
  14. #include <boost/beast/core/buffers_suffix.hpp>
  15. #include <boost/beast/core/string.hpp>
  16. #include <boost/beast/core/detail/variant.hpp>
  17. #include <boost/beast/http/message.hpp>
  18. #include <boost/beast/http/chunk_encode.hpp>
  19. #include <boost/asio/buffer.hpp>
  20. #include <boost/optional.hpp>
  21. namespace boost {
  22. namespace beast {
  23. namespace http {
  24. /** Provides buffer oriented HTTP message serialization functionality.
  25. An object of this type is used to serialize a complete
  26. HTTP message into a sequence of octets. To use this class,
  27. construct an instance with the message to be serialized.
  28. The implementation will automatically perform chunk encoding
  29. if the contents of the message indicate that chunk encoding
  30. is required.
  31. Chunked output produced by the serializer never contains chunk
  32. extensions or trailers, and the location of chunk boundaries
  33. is not specified. If callers require chunk extensions, trailers,
  34. or control over the exact contents of each chunk they should
  35. use the serializer to write just the message header, and then
  36. assume control over serializing the chunked payload by using
  37. the chunk buffer sequence types @ref chunk_body, @ref chunk_crlf,
  38. @ref chunk_header, and @ref chunk_last.
  39. @tparam isRequest `true` if the message is a request.
  40. @tparam Body The body type of the message.
  41. @tparam Fields The type of fields in the message.
  42. */
  43. template<
  44. bool isRequest,
  45. class Body,
  46. class Fields = fields>
  47. class serializer
  48. {
  49. public:
  50. static_assert(is_body<Body>::value,
  51. "Body type requirements not met");
  52. static_assert(is_body_writer<Body>::value,
  53. "BodyWriter type requirements not met");
  54. /** The type of message this serializer uses
  55. This may be const or non-const depending on the
  56. implementation of the corresponding <em>BodyWriter</em>.
  57. */
  58. #if BOOST_BEAST_DOXYGEN
  59. using value_type = __implementation_defined__;
  60. #else
  61. using value_type = typename std::conditional<
  62. std::is_constructible<typename Body::writer,
  63. header<isRequest, Fields>&,
  64. typename Body::value_type&>::value &&
  65. ! std::is_constructible<typename Body::writer,
  66. header<isRequest, Fields> const&,
  67. typename Body::value_type const&>::value,
  68. message<isRequest, Body, Fields>,
  69. message<isRequest, Body, Fields> const>::type;
  70. #endif
  71. private:
  72. enum
  73. {
  74. do_construct = 0,
  75. do_init = 10,
  76. do_header_only = 20,
  77. do_header = 30,
  78. do_body = 40,
  79. do_init_c = 50,
  80. do_header_only_c = 60,
  81. do_header_c = 70,
  82. do_body_c = 80,
  83. do_final_c = 90,
  84. #ifndef BOOST_BEAST_NO_BIG_VARIANTS
  85. do_body_final_c = 100,
  86. do_all_c = 110,
  87. #endif
  88. do_complete = 120
  89. };
  90. void fwrinit(std::true_type);
  91. void fwrinit(std::false_type);
  92. template<std::size_t, class Visit>
  93. void
  94. do_visit(error_code& ec, Visit& visit);
  95. using writer = typename Body::writer;
  96. using cb1_t = buffers_suffix<typename
  97. Fields::writer::const_buffers_type>; // header
  98. using pcb1_t = buffers_prefix_view<cb1_t const&>;
  99. using cb2_t = buffers_suffix<buffers_cat_view<
  100. typename Fields::writer::const_buffers_type,// header
  101. typename writer::const_buffers_type>>; // body
  102. using pcb2_t = buffers_prefix_view<cb2_t const&>;
  103. using cb3_t = buffers_suffix<
  104. typename writer::const_buffers_type>; // body
  105. using pcb3_t = buffers_prefix_view<cb3_t const&>;
  106. using cb4_t = buffers_suffix<buffers_cat_view<
  107. typename Fields::writer::const_buffers_type,// header
  108. detail::chunk_size, // chunk-size
  109. net::const_buffer, // chunk-ext
  110. chunk_crlf, // crlf
  111. typename writer::const_buffers_type, // body
  112. chunk_crlf>>; // crlf
  113. using pcb4_t = buffers_prefix_view<cb4_t const&>;
  114. using cb5_t = buffers_suffix<buffers_cat_view<
  115. detail::chunk_size, // chunk-header
  116. net::const_buffer, // chunk-ext
  117. chunk_crlf, // crlf
  118. typename writer::const_buffers_type, // body
  119. chunk_crlf>>; // crlf
  120. using pcb5_t = buffers_prefix_view<cb5_t const&>;
  121. using cb6_t = buffers_suffix<buffers_cat_view<
  122. detail::chunk_size, // chunk-header
  123. net::const_buffer, // chunk-size
  124. chunk_crlf, // crlf
  125. typename writer::const_buffers_type, // body
  126. chunk_crlf, // crlf
  127. net::const_buffer, // chunk-final
  128. net::const_buffer, // trailers
  129. chunk_crlf>>; // crlf
  130. using pcb6_t = buffers_prefix_view<cb6_t const&>;
  131. using cb7_t = buffers_suffix<buffers_cat_view<
  132. typename Fields::writer::const_buffers_type,// header
  133. detail::chunk_size, // chunk-size
  134. net::const_buffer, // chunk-ext
  135. chunk_crlf, // crlf
  136. typename writer::const_buffers_type, // body
  137. chunk_crlf, // crlf
  138. net::const_buffer, // chunk-final
  139. net::const_buffer, // trailers
  140. chunk_crlf>>; // crlf
  141. using pcb7_t = buffers_prefix_view<cb7_t const&>;
  142. using cb8_t = buffers_suffix<buffers_cat_view<
  143. net::const_buffer, // chunk-final
  144. net::const_buffer, // trailers
  145. chunk_crlf>>; // crlf
  146. using pcb8_t = buffers_prefix_view<cb8_t const&>;
  147. value_type& m_;
  148. writer wr_;
  149. boost::optional<typename Fields::writer> fwr_;
  150. beast::detail::variant<
  151. cb1_t, cb2_t, cb3_t, cb4_t,
  152. cb5_t ,cb6_t, cb7_t, cb8_t> v_;
  153. beast::detail::variant<
  154. pcb1_t, pcb2_t, pcb3_t, pcb4_t,
  155. pcb5_t ,pcb6_t, pcb7_t, pcb8_t> pv_;
  156. std::size_t limit_ =
  157. (std::numeric_limits<std::size_t>::max)();
  158. int s_ = do_construct;
  159. bool split_ = false;
  160. bool header_done_ = false;
  161. bool more_ = false;
  162. public:
  163. /// Constructor
  164. serializer(serializer&&) = default;
  165. /// Constructor
  166. serializer(serializer const&) = default;
  167. /// Assignment
  168. serializer& operator=(serializer const&) = delete;
  169. /** Constructor
  170. The implementation guarantees that the message passed on
  171. construction will not be accessed until the first call to
  172. @ref next. This allows the message to be lazily created.
  173. For example, if the header is filled in before serialization.
  174. @param msg A reference to the message to serialize, which must
  175. remain valid for the lifetime of the serializer. Depending on
  176. the type of Body used, this may or may not be a `const` reference.
  177. @note This function participates in overload resolution only if
  178. Body::writer is constructible from a `const` message reference.
  179. */
  180. explicit
  181. serializer(value_type& msg);
  182. /// Returns the message being serialized
  183. value_type&
  184. get()
  185. {
  186. return m_;
  187. }
  188. /// Returns the serialized buffer size limit
  189. std::size_t
  190. limit()
  191. {
  192. return limit_;
  193. }
  194. /** Set the serialized buffer size limit
  195. This function adjusts the limit on the maximum size of the
  196. buffers passed to the visitor. The new size limit takes effect
  197. in the following call to @ref next.
  198. The default is no buffer size limit.
  199. @param limit The new buffer size limit. If this number
  200. is zero, the size limit is removed.
  201. */
  202. void
  203. limit(std::size_t limit)
  204. {
  205. limit_ = limit > 0 ? limit :
  206. (std::numeric_limits<std::size_t>::max)();
  207. }
  208. /** Returns `true` if we will pause after writing the complete header.
  209. */
  210. bool
  211. split()
  212. {
  213. return split_;
  214. }
  215. /** Set whether the header and body are written separately.
  216. When the split feature is enabled, the implementation will
  217. write only the octets corresponding to the serialized header
  218. first. If the header has already been written, this function
  219. will have no effect on output.
  220. */
  221. void
  222. split(bool v)
  223. {
  224. split_ = v;
  225. }
  226. /** Return `true` if serialization of the header is complete.
  227. This function indicates whether or not all buffers containing
  228. serialized header octets have been retrieved.
  229. */
  230. bool
  231. is_header_done()
  232. {
  233. return header_done_;
  234. }
  235. /** Return `true` if serialization is complete.
  236. The operation is complete when all octets corresponding
  237. to the serialized representation of the message have been
  238. successfully retrieved.
  239. */
  240. bool
  241. is_done()
  242. {
  243. return s_ == do_complete;
  244. }
  245. /** Returns the next set of buffers in the serialization.
  246. This function will attempt to call the `visit` function
  247. object with a <em>ConstBufferSequence</em> of unspecified type
  248. representing the next set of buffers in the serialization
  249. of the message represented by this object.
  250. If there are no more buffers in the serialization, the
  251. visit function will not be called. In this case, no error
  252. will be indicated, and the function @ref is_done will
  253. return `true`.
  254. @param ec Set to the error, if any occurred.
  255. @param visit The function to call. The equivalent function
  256. signature of this object must be:
  257. @code
  258. template<class ConstBufferSequence>
  259. void visit(error_code&, ConstBufferSequence const&);
  260. @endcode
  261. The function is not copied, if no error occurs it will be
  262. invoked before the call to @ref next returns.
  263. */
  264. template<class Visit>
  265. void
  266. next(error_code& ec, Visit&& visit);
  267. /** Consume buffer octets in the serialization.
  268. This function should be called after one or more octets
  269. contained in the buffers provided in the prior call
  270. to @ref next have been used.
  271. After a call to @ref consume, callers should check the
  272. return value of @ref is_done to determine if the entire
  273. message has been serialized.
  274. @param n The number of octets to consume. This number must
  275. be greater than zero and no greater than the number of
  276. octets in the buffers provided in the prior call to @ref next.
  277. */
  278. void
  279. consume(std::size_t n);
  280. /** Provides low-level access to the associated <em>BodyWriter</em>
  281. This function provides access to the instance of the writer
  282. associated with the body and created by the serializer
  283. upon construction. The behavior of accessing this object
  284. is defined by the specification of the particular writer
  285. and its associated body.
  286. @return A reference to the writer.
  287. */
  288. writer&
  289. writer_impl()
  290. {
  291. return wr_;
  292. }
  293. };
  294. /// A serializer for HTTP/1 requests
  295. template<class Body, class Fields = fields>
  296. using request_serializer = serializer<true, Body, Fields>;
  297. /// A serializer for HTTP/1 responses
  298. template<class Body, class Fields = fields>
  299. using response_serializer = serializer<false, Body, Fields>;
  300. } // http
  301. } // beast
  302. } // boost
  303. #include <boost/beast/http/impl/serializer.hpp>
  304. #endif