exemplars.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  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. #include <boost/beast/core/buffer_traits.hpp>
  10. #include <boost/beast/core/error.hpp>
  11. #include <boost/beast/core/file_base.hpp>
  12. #include <boost/beast/http/message.hpp>
  13. #include <boost/beast/http/type_traits.hpp>
  14. #include <boost/optional.hpp>
  15. #include <cstdint>
  16. #include <utility>
  17. namespace boost {
  18. namespace beast {
  19. namespace http {
  20. class BodyWriter;
  21. class BodyReader;
  22. //[concept_Body
  23. struct Body
  24. {
  25. // The type of message::body when used
  26. struct value_type;
  27. /// The algorithm used during parsing
  28. class reader;
  29. /// The algorithm used during serialization
  30. class writer;
  31. /// Returns the body's payload size
  32. static
  33. std::uint64_t
  34. size(value_type const& body);
  35. };
  36. static_assert(is_body<Body>::value, "");
  37. //]
  38. struct Body_BodyWriter {
  39. struct value_type{};
  40. //[concept_BodyWriter
  41. struct BodyWriter
  42. {
  43. public:
  44. /// The type of buffer returned by `get`.
  45. using const_buffers_type = net::const_buffer;
  46. /** Construct the writer.
  47. @param h The header for the message being serialized
  48. @param body The body being serialized
  49. */
  50. template<bool isRequest, class Fields>
  51. BodyWriter(header<isRequest, Fields> const& h, value_type const& body);
  52. /** Initialize the writer.
  53. This is called after construction and before the first
  54. call to `get`. The message is valid and complete upon
  55. entry.
  56. @param ec Set to the error, if any occurred.
  57. */
  58. void
  59. init(error_code& ec)
  60. {
  61. // The specification requires this to indicate "no error"
  62. ec = {};
  63. }
  64. /** Returns the next buffer in the body.
  65. @li If the return value is `boost::none` (unseated optional) and
  66. `ec` does not contain an error, this indicates the end of the
  67. body, no more buffers are present.
  68. @li If the optional contains a value, the first element of the
  69. pair represents a <em>ConstBufferSequence</em> containing one or
  70. more octets of the body data. The second element indicates
  71. whether or not there are additional octets of body data.
  72. A value of `true` means there is more data, and that the
  73. implementation will perform a subsequent call to `get`.
  74. A value of `false` means there is no more body data.
  75. @li If `ec` contains an error code, the return value is ignored.
  76. @param ec Set to the error, if any occurred.
  77. */
  78. boost::optional<std::pair<const_buffers_type, bool>>
  79. get(error_code& ec)
  80. {
  81. // The specification requires this to indicate "no error"
  82. ec = {};
  83. return boost::none; // for exposition only
  84. }
  85. };
  86. //]
  87. using writer = BodyWriter;
  88. };
  89. static_assert(is_body_writer<Body_BodyWriter>::value, "");
  90. struct Body_BodyReader {
  91. struct value_type{};
  92. //[concept_BodyReader
  93. struct BodyReader
  94. {
  95. /** Construct the reader.
  96. @param h The header for the message being parsed
  97. @param body The body to store the parsed results into
  98. */
  99. template<bool isRequest, class Fields>
  100. BodyReader(header<isRequest, Fields>& h, value_type& body);
  101. /** Initialize the reader.
  102. This is called after construction and before the first
  103. call to `put`. The message is valid and complete upon
  104. entry.
  105. @param ec Set to the error, if any occurred.
  106. */
  107. void
  108. init(
  109. boost::optional<std::uint64_t> const& content_length,
  110. error_code& ec)
  111. {
  112. boost::ignore_unused(content_length);
  113. // The specification requires this to indicate "no error"
  114. ec = {};
  115. }
  116. /** Store buffers.
  117. This is called zero or more times with parsed body octets.
  118. @param buffers The constant buffer sequence to store.
  119. @param ec Set to the error, if any occurred.
  120. @return The number of bytes transferred from the input buffers.
  121. */
  122. template<class ConstBufferSequence>
  123. std::size_t
  124. put(ConstBufferSequence const& buffers, error_code& ec)
  125. {
  126. // The specification requires this to indicate "no error"
  127. ec = {};
  128. return buffer_bytes(buffers);
  129. }
  130. /** Called when the body is complete.
  131. @param ec Set to the error, if any occurred.
  132. */
  133. void
  134. finish(error_code& ec)
  135. {
  136. // The specification requires this to indicate "no error"
  137. ec = {};
  138. }
  139. };
  140. //]
  141. using reader = BodyReader;
  142. };
  143. static_assert(is_body_reader<Body_BodyReader>::value, "");
  144. //[concept_Fields
  145. class Fields
  146. {
  147. public:
  148. /// Constructed as needed when fields are serialized
  149. struct writer;
  150. protected:
  151. /** Returns the request-method string.
  152. @note Only called for requests.
  153. */
  154. string_view
  155. get_method_impl() const;
  156. /** Returns the request-target string.
  157. @note Only called for requests.
  158. */
  159. string_view
  160. get_target_impl() const;
  161. /** Returns the response reason-phrase string.
  162. @note Only called for responses.
  163. */
  164. string_view
  165. get_reason_impl() const;
  166. /** Returns the chunked Transfer-Encoding setting
  167. */
  168. bool
  169. get_chunked_impl() const;
  170. /** Returns the keep-alive setting
  171. */
  172. bool
  173. get_keep_alive_impl(unsigned version) const;
  174. /** Returns `true` if the Content-Length field is present.
  175. */
  176. bool
  177. has_content_length_impl() const;
  178. /** Set or clear the method string.
  179. @note Only called for requests.
  180. */
  181. void
  182. set_method_impl(string_view s);
  183. /** Set or clear the target string.
  184. @note Only called for requests.
  185. */
  186. void
  187. set_target_impl(string_view s);
  188. /** Set or clear the reason string.
  189. @note Only called for responses.
  190. */
  191. void
  192. set_reason_impl(string_view s);
  193. /** Sets or clears the chunked Transfer-Encoding value
  194. */
  195. void
  196. set_chunked_impl(bool value);
  197. /** Sets or clears the Content-Length field
  198. */
  199. void
  200. set_content_length_impl(boost::optional<std::uint64_t>);
  201. /** Adjusts the Connection field
  202. */
  203. void
  204. set_keep_alive_impl(unsigned version, bool keep_alive);
  205. };
  206. static_assert(is_fields<Fields>::value,
  207. "Fields type requirements not met");
  208. //]
  209. struct Fields_FieldsWriter {
  210. using Fields = Fields_FieldsWriter;
  211. //[concept_FieldsWriter
  212. struct FieldsWriter
  213. {
  214. // The type of buffers returned by `get`
  215. struct const_buffers_type;
  216. // Constructor for requests
  217. FieldsWriter(Fields const& f, unsigned version, verb method);
  218. // Constructor for responses
  219. FieldsWriter(Fields const& f, unsigned version, unsigned status);
  220. // Returns the serialized header buffers
  221. const_buffers_type
  222. get();
  223. };
  224. //]
  225. };
  226. //[concept_File
  227. struct File
  228. {
  229. /** Default constructor
  230. There is no open file initially.
  231. */
  232. File();
  233. /** Destructor
  234. If the file is open it is first closed.
  235. */
  236. ~File();
  237. /// Returns `true` if the file is open
  238. bool
  239. is_open() const;
  240. /// Close the file if open
  241. void
  242. close(error_code& ec);
  243. /// Open a file at the given path with the specified mode
  244. void
  245. open(char const* path, file_mode mode, error_code& ec);
  246. /// Return the size of the open file
  247. std::uint64_t
  248. size(error_code& ec) const;
  249. /// Return the current position in the open file
  250. std::uint64_t
  251. pos(error_code& ec) const;
  252. /// Adjust the current position in the open file
  253. void
  254. seek(std::uint64_t offset, error_code& ec);
  255. /// Read from the open file
  256. std::size_t
  257. read(void* buffer, std::size_t n, error_code& ec) const;
  258. /// Write to the open file
  259. std::size_t
  260. write(void const* buffer, std::size_t n, error_code& ec);
  261. };
  262. //]
  263. } // http
  264. } // beast
  265. } // boost