serializer.hpp 12 KB

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