write.hpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  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_IMPL_WRITE_HPP
  10. #define BOOST_BEAST_HTTP_IMPL_WRITE_HPP
  11. #include <boost/beast/http/type_traits.hpp>
  12. #include <boost/beast/core/async_base.hpp>
  13. #include <boost/beast/core/buffers_range.hpp>
  14. #include <boost/beast/core/make_printable.hpp>
  15. #include <boost/beast/core/stream_traits.hpp>
  16. #include <boost/beast/core/detail/is_invocable.hpp>
  17. #include <boost/asio/append.hpp>
  18. #include <boost/asio/coroutine.hpp>
  19. #include <boost/asio/dispatch.hpp>
  20. #include <boost/asio/write.hpp>
  21. #include <boost/optional.hpp>
  22. #include <boost/throw_exception.hpp>
  23. #include <ostream>
  24. #include <sstream>
  25. namespace boost {
  26. namespace beast {
  27. namespace http {
  28. namespace detail {
  29. template<
  30. class Handler,
  31. class Stream,
  32. bool isRequest, class Body, class Fields>
  33. class write_some_op
  34. : public beast::async_base<
  35. Handler, beast::executor_type<Stream>>
  36. {
  37. Stream& s_;
  38. serializer<isRequest,Body, Fields>& sr_;
  39. class lambda
  40. {
  41. write_some_op& op_;
  42. public:
  43. bool invoked = false;
  44. explicit
  45. lambda(write_some_op& op)
  46. : op_(op)
  47. {
  48. }
  49. template<class ConstBufferSequence>
  50. void
  51. operator()(
  52. error_code& ec,
  53. ConstBufferSequence const& buffers)
  54. {
  55. BOOST_ASIO_HANDLER_LOCATION((
  56. __FILE__, __LINE__,
  57. "http::async_write_some"));
  58. invoked = true;
  59. ec = {};
  60. op_.s_.async_write_some(
  61. buffers, std::move(op_));
  62. }
  63. };
  64. public:
  65. template<class Handler_>
  66. write_some_op(
  67. Handler_&& h,
  68. Stream& s,
  69. serializer<isRequest, Body, Fields>& sr)
  70. : async_base<
  71. Handler, beast::executor_type<Stream>>(
  72. std::forward<Handler_>(h), s.get_executor())
  73. , s_(s)
  74. , sr_(sr)
  75. {
  76. (*this)();
  77. }
  78. void
  79. operator()()
  80. {
  81. error_code ec;
  82. if(! sr_.is_done())
  83. {
  84. lambda f{*this};
  85. sr_.next(ec, f);
  86. if(ec)
  87. {
  88. BOOST_ASSERT(! f.invoked);
  89. BOOST_ASIO_HANDLER_LOCATION((
  90. __FILE__, __LINE__,
  91. "http::async_write_some"));
  92. const auto ex = asio::get_associated_immediate_executor(*this, s_.get_executor());
  93. return net::dispatch(ex, net::append(std::move(*this), ec, 0));
  94. }
  95. if(f.invoked)
  96. {
  97. // *this is now moved-from,
  98. return;
  99. }
  100. // What else could it be?
  101. BOOST_ASSERT(sr_.is_done());
  102. }
  103. BOOST_ASIO_HANDLER_LOCATION((
  104. __FILE__, __LINE__,
  105. "http::async_write_some"));
  106. const auto ex = this->get_immediate_executor();
  107. return net::dispatch(ex, net::append(std::move(*this), ec, 0));
  108. }
  109. void
  110. operator()(
  111. error_code ec,
  112. std::size_t bytes_transferred)
  113. {
  114. if(! ec)
  115. sr_.consume(bytes_transferred);
  116. this->complete_now(ec, bytes_transferred);
  117. }
  118. };
  119. //------------------------------------------------------------------------------
  120. struct serializer_is_header_done
  121. {
  122. template<
  123. bool isRequest, class Body, class Fields>
  124. bool
  125. operator()(
  126. serializer<isRequest, Body, Fields>& sr) const
  127. {
  128. return sr.is_header_done();
  129. }
  130. };
  131. struct serializer_is_done
  132. {
  133. template<
  134. bool isRequest, class Body, class Fields>
  135. bool
  136. operator()(
  137. serializer<isRequest, Body, Fields>& sr) const
  138. {
  139. return sr.is_done();
  140. }
  141. };
  142. //------------------------------------------------------------------------------
  143. template<
  144. class Handler,
  145. class Stream,
  146. class Predicate,
  147. bool isRequest, class Body, class Fields>
  148. class write_op
  149. : public beast::async_base<
  150. Handler, beast::executor_type<Stream>>
  151. , public asio::coroutine
  152. {
  153. Stream& s_;
  154. serializer<isRequest, Body, Fields>& sr_;
  155. std::size_t bytes_transferred_ = 0;
  156. net::cancellation_state st_{this->
  157. beast::async_base<Handler, beast::executor_type<Stream>>
  158. ::get_cancellation_slot()};
  159. public:
  160. using cancellation_slot_type = net::cancellation_slot;
  161. cancellation_slot_type get_cancellation_slot() const noexcept
  162. {
  163. return st_.slot();
  164. }
  165. template<class Handler_>
  166. write_op(
  167. Handler_&& h,
  168. Stream& s,
  169. serializer<isRequest, Body, Fields>& sr)
  170. : async_base<
  171. Handler, beast::executor_type<Stream>>(
  172. std::forward<Handler_>(h), s.get_executor())
  173. , s_(s)
  174. , sr_(sr)
  175. {
  176. (*this)();
  177. }
  178. void
  179. operator()(
  180. error_code ec = {},
  181. std::size_t bytes_transferred = 0)
  182. {
  183. BOOST_ASIO_CORO_REENTER(*this)
  184. {
  185. if(Predicate{}(sr_))
  186. {
  187. BOOST_ASIO_CORO_YIELD
  188. {
  189. BOOST_ASIO_HANDLER_LOCATION((
  190. __FILE__, __LINE__,
  191. "http::async_write"));
  192. const auto ex = this->get_immediate_executor();
  193. net::dispatch(
  194. ex,
  195. std::move(*this));
  196. }
  197. goto upcall;
  198. }
  199. for(;;)
  200. {
  201. BOOST_ASIO_CORO_YIELD
  202. {
  203. BOOST_ASIO_HANDLER_LOCATION((
  204. __FILE__, __LINE__,
  205. "http::async_write"));
  206. beast::http::async_write_some(
  207. s_, sr_, std::move(*this));
  208. }
  209. bytes_transferred_ += bytes_transferred;
  210. if (!ec && st_.cancelled() != net::cancellation_type::none)
  211. {
  212. BOOST_BEAST_ASSIGN_EC(ec, net::error::operation_aborted);
  213. }
  214. if(ec)
  215. goto upcall;
  216. if(Predicate{}(sr_))
  217. break;
  218. }
  219. upcall:
  220. this->complete_now(ec, bytes_transferred_);
  221. }
  222. }
  223. };
  224. //------------------------------------------------------------------------------
  225. template<
  226. class Handler,
  227. class Stream,
  228. bool isRequest, class Body, class Fields>
  229. class write_msg_op
  230. : public beast::stable_async_base<
  231. Handler, beast::executor_type<Stream>>
  232. {
  233. Stream& s_;
  234. serializer<isRequest, Body, Fields>& sr_;
  235. public:
  236. template<
  237. class Handler_,
  238. class... Args>
  239. write_msg_op(
  240. Handler_&& h,
  241. Stream& s,
  242. Args&&... args)
  243. : stable_async_base<
  244. Handler, beast::executor_type<Stream>>(
  245. std::forward<Handler_>(h), s.get_executor())
  246. , s_(s)
  247. , sr_(beast::allocate_stable<
  248. serializer<isRequest, Body, Fields>>(
  249. *this, std::forward<Args>(args)...))
  250. {
  251. (*this)();
  252. }
  253. void
  254. operator()()
  255. {
  256. BOOST_ASIO_HANDLER_LOCATION((
  257. __FILE__, __LINE__,
  258. "http::async_write(msg)"));
  259. async_write(s_, sr_, std::move(*this));
  260. }
  261. void
  262. operator()(
  263. error_code ec, std::size_t bytes_transferred)
  264. {
  265. this->complete_now(ec, bytes_transferred);
  266. }
  267. };
  268. template <typename AsyncWriteStream>
  269. struct run_write_some_op
  270. {
  271. AsyncWriteStream* stream;
  272. using executor_type = typename AsyncWriteStream::executor_type;
  273. executor_type
  274. get_executor() const noexcept
  275. {
  276. return stream->get_executor();
  277. }
  278. template<
  279. class WriteHandler,
  280. bool isRequest, class Body, class Fields>
  281. void
  282. operator()(
  283. WriteHandler&& h,
  284. serializer<isRequest, Body, Fields>* sr)
  285. {
  286. // If you get an error on the following line it means
  287. // that your handler does not meet the documented type
  288. // requirements for the handler.
  289. static_assert(
  290. beast::detail::is_invocable<WriteHandler,
  291. void(error_code, std::size_t)>::value,
  292. "WriteHandler type requirements not met");
  293. write_some_op<
  294. typename std::decay<WriteHandler>::type,
  295. AsyncWriteStream,
  296. isRequest, Body, Fields>(
  297. std::forward<WriteHandler>(h), *stream, *sr);
  298. }
  299. };
  300. template <typename AsyncWriteStream>
  301. struct run_write_op
  302. {
  303. AsyncWriteStream* stream;
  304. using executor_type = typename AsyncWriteStream::executor_type;
  305. executor_type
  306. get_executor() const noexcept
  307. {
  308. return stream->get_executor();
  309. }
  310. template<
  311. class WriteHandler,
  312. class Predicate,
  313. bool isRequest, class Body, class Fields>
  314. void
  315. operator()(
  316. WriteHandler&& h,
  317. Predicate const&,
  318. serializer<isRequest, Body, Fields>* sr)
  319. {
  320. // If you get an error on the following line it means
  321. // that your handler does not meet the documented type
  322. // requirements for the handler.
  323. static_assert(
  324. beast::detail::is_invocable<WriteHandler,
  325. void(error_code, std::size_t)>::value,
  326. "WriteHandler type requirements not met");
  327. write_op<
  328. typename std::decay<WriteHandler>::type,
  329. AsyncWriteStream,
  330. Predicate,
  331. isRequest, Body, Fields>(
  332. std::forward<WriteHandler>(h), *stream, *sr);
  333. }
  334. };
  335. template <typename AsyncWriteStream>
  336. struct run_write_msg_op
  337. {
  338. AsyncWriteStream* stream;
  339. using executor_type = typename AsyncWriteStream::executor_type;
  340. executor_type
  341. get_executor() const noexcept
  342. {
  343. return stream->get_executor();
  344. }
  345. template<
  346. class WriteHandler,
  347. bool isRequest, class Body, class Fields,
  348. class... Args>
  349. void
  350. operator()(
  351. WriteHandler&& h,
  352. message<isRequest, Body, Fields>* m,
  353. std::false_type,
  354. Args&&... args)
  355. {
  356. // If you get an error on the following line it means
  357. // that your handler does not meet the documented type
  358. // requirements for the handler.
  359. static_assert(
  360. beast::detail::is_invocable<WriteHandler,
  361. void(error_code, std::size_t)>::value,
  362. "WriteHandler type requirements not met");
  363. write_msg_op<
  364. typename std::decay<WriteHandler>::type,
  365. AsyncWriteStream,
  366. isRequest, Body, Fields>(
  367. std::forward<WriteHandler>(h), *stream, *m,
  368. std::forward<Args>(args)...);
  369. }
  370. template<
  371. class WriteHandler,
  372. bool isRequest, class Body, class Fields,
  373. class... Args>
  374. void
  375. operator()(
  376. WriteHandler&& h,
  377. message<isRequest, Body, Fields> const* m,
  378. std::true_type,
  379. Args&&... args)
  380. {
  381. // If you get an error on the following line it means
  382. // that your handler does not meet the documented type
  383. // requirements for the handler.
  384. static_assert(
  385. beast::detail::is_invocable<WriteHandler,
  386. void(error_code, std::size_t)>::value,
  387. "WriteHandler type requirements not met");
  388. write_msg_op<
  389. typename std::decay<WriteHandler>::type,
  390. AsyncWriteStream,
  391. isRequest, Body, Fields>(
  392. std::forward<WriteHandler>(h), *stream, *m,
  393. std::forward<Args>(args)...);
  394. }
  395. };
  396. //------------------------------------------------------------------------------
  397. template<class Stream>
  398. class write_some_lambda
  399. {
  400. Stream& stream_;
  401. public:
  402. bool invoked = false;
  403. std::size_t bytes_transferred = 0;
  404. explicit
  405. write_some_lambda(Stream& stream)
  406. : stream_(stream)
  407. {
  408. }
  409. template<class ConstBufferSequence>
  410. void
  411. operator()(error_code& ec,
  412. ConstBufferSequence const& buffers)
  413. {
  414. invoked = true;
  415. bytes_transferred =
  416. stream_.write_some(buffers, ec);
  417. }
  418. };
  419. template<class Stream>
  420. class write_lambda
  421. {
  422. Stream& stream_;
  423. public:
  424. bool invoked = false;
  425. std::size_t bytes_transferred = 0;
  426. explicit
  427. write_lambda(Stream& stream)
  428. : stream_(stream)
  429. {
  430. }
  431. template<class ConstBufferSequence>
  432. void
  433. operator()(error_code& ec,
  434. ConstBufferSequence const& buffers)
  435. {
  436. invoked = true;
  437. bytes_transferred = net::write(
  438. stream_, buffers, ec);
  439. }
  440. };
  441. template<
  442. class SyncWriteStream,
  443. bool isRequest, class Body, class Fields>
  444. std::size_t
  445. write_some_impl(
  446. SyncWriteStream& stream,
  447. serializer<isRequest, Body, Fields>& sr,
  448. error_code& ec)
  449. {
  450. if(! sr.is_done())
  451. {
  452. write_some_lambda<SyncWriteStream> f{stream};
  453. sr.next(ec, f);
  454. if(ec)
  455. return f.bytes_transferred;
  456. if(f.invoked)
  457. sr.consume(f.bytes_transferred);
  458. return f.bytes_transferred;
  459. }
  460. ec = {};
  461. return 0;
  462. }
  463. template<
  464. class AsyncWriteStream,
  465. bool isRequest, class Body, class Fields,
  466. BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
  467. BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
  468. async_write_some_impl(
  469. AsyncWriteStream& stream,
  470. serializer<isRequest, Body, Fields>& sr,
  471. WriteHandler&& handler)
  472. {
  473. return net::async_initiate<
  474. WriteHandler,
  475. void(error_code, std::size_t)>(
  476. run_write_some_op<AsyncWriteStream>{&stream},
  477. handler,
  478. &sr);
  479. }
  480. } // detail
  481. //------------------------------------------------------------------------------
  482. template<
  483. class SyncWriteStream,
  484. bool isRequest, class Body, class Fields>
  485. std::size_t
  486. write_some(
  487. SyncWriteStream& stream,
  488. serializer<isRequest, Body, Fields>& sr)
  489. {
  490. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  491. "SyncWriteStream type requirements not met");
  492. static_assert(is_body<Body>::value,
  493. "Body type requirements not met");
  494. static_assert(is_body_writer<Body>::value,
  495. "BodyWriter type requirements not met");
  496. error_code ec;
  497. auto const bytes_transferred =
  498. write_some(stream, sr, ec);
  499. if(ec)
  500. BOOST_THROW_EXCEPTION(system_error{ec});
  501. return bytes_transferred;
  502. }
  503. template<
  504. class SyncWriteStream,
  505. bool isRequest, class Body, class Fields>
  506. std::size_t
  507. write_some(
  508. SyncWriteStream& stream,
  509. serializer<isRequest, Body, Fields>& sr,
  510. error_code& ec)
  511. {
  512. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  513. "SyncWriteStream type requirements not met");
  514. static_assert(is_body<Body>::value,
  515. "Body type requirements not met");
  516. static_assert(is_body_writer<Body>::value,
  517. "BodyWriter type requirements not met");
  518. return detail::write_some_impl(stream, sr, ec);
  519. }
  520. template<
  521. class AsyncWriteStream,
  522. bool isRequest, class Body, class Fields,
  523. BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
  524. BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
  525. async_write_some(
  526. AsyncWriteStream& stream,
  527. serializer<isRequest, Body, Fields>& sr,
  528. WriteHandler&& handler)
  529. {
  530. static_assert(is_async_write_stream<
  531. AsyncWriteStream>::value,
  532. "AsyncWriteStream type requirements not met");
  533. static_assert(is_body<Body>::value,
  534. "Body type requirements not met");
  535. static_assert(is_body_writer<Body>::value,
  536. "BodyWriter type requirements not met");
  537. return detail::async_write_some_impl(stream, sr,
  538. std::forward<WriteHandler>(handler));
  539. }
  540. //------------------------------------------------------------------------------
  541. template<
  542. class SyncWriteStream,
  543. bool isRequest, class Body, class Fields>
  544. std::size_t
  545. write_header(SyncWriteStream& stream,
  546. serializer<isRequest, Body, Fields>& sr)
  547. {
  548. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  549. "SyncWriteStream type requirements not met");
  550. static_assert(is_body<Body>::value,
  551. "Body type requirements not met");
  552. static_assert(is_body_writer<Body>::value,
  553. "BodyWriter type requirements not met");
  554. error_code ec;
  555. auto const bytes_transferred =
  556. write_header(stream, sr, ec);
  557. if(ec)
  558. BOOST_THROW_EXCEPTION(system_error{ec});
  559. return bytes_transferred;
  560. }
  561. template<
  562. class SyncWriteStream,
  563. bool isRequest, class Body, class Fields>
  564. std::size_t
  565. write_header(
  566. SyncWriteStream& stream,
  567. serializer<isRequest, Body, Fields>& sr,
  568. error_code& ec)
  569. {
  570. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  571. "SyncWriteStream type requirements not met");
  572. static_assert(is_body<Body>::value,
  573. "Body type requirements not met");
  574. static_assert(is_body_writer<Body>::value,
  575. "BodyWriter type requirements not met");
  576. sr.split(true);
  577. std::size_t bytes_transferred = 0;
  578. if(! sr.is_header_done())
  579. {
  580. detail::write_lambda<SyncWriteStream> f{stream};
  581. do
  582. {
  583. sr.next(ec, f);
  584. bytes_transferred += f.bytes_transferred;
  585. if(ec)
  586. return bytes_transferred;
  587. BOOST_ASSERT(f.invoked);
  588. sr.consume(f.bytes_transferred);
  589. }
  590. while(! sr.is_header_done());
  591. }
  592. else
  593. {
  594. ec = {};
  595. }
  596. return bytes_transferred;
  597. }
  598. template<
  599. class AsyncWriteStream,
  600. bool isRequest, class Body, class Fields,
  601. BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
  602. BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
  603. async_write_header(
  604. AsyncWriteStream& stream,
  605. serializer<isRequest, Body, Fields>& sr,
  606. WriteHandler&& handler)
  607. {
  608. static_assert(is_async_write_stream<
  609. AsyncWriteStream>::value,
  610. "AsyncWriteStream type requirements not met");
  611. static_assert(is_body<Body>::value,
  612. "Body type requirements not met");
  613. static_assert(is_body_writer<Body>::value,
  614. "BodyWriter type requirements not met");
  615. sr.split(true);
  616. return net::async_initiate<
  617. WriteHandler,
  618. void(error_code, std::size_t)>(
  619. detail::run_write_op<AsyncWriteStream>{&stream},
  620. handler,
  621. detail::serializer_is_header_done{},
  622. &sr);
  623. }
  624. //------------------------------------------------------------------------------
  625. template<
  626. class SyncWriteStream,
  627. bool isRequest, class Body, class Fields>
  628. std::size_t
  629. write(
  630. SyncWriteStream& stream,
  631. serializer<isRequest, Body, Fields>& sr)
  632. {
  633. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  634. "SyncWriteStream type requirements not met");
  635. error_code ec;
  636. auto const bytes_transferred =
  637. write(stream, sr, ec);
  638. if(ec)
  639. BOOST_THROW_EXCEPTION(system_error{ec});
  640. return bytes_transferred;
  641. }
  642. template<
  643. class SyncWriteStream,
  644. bool isRequest, class Body, class Fields>
  645. std::size_t
  646. write(
  647. SyncWriteStream& stream,
  648. serializer<isRequest, Body, Fields>& sr,
  649. error_code& ec)
  650. {
  651. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  652. "SyncWriteStream type requirements not met");
  653. std::size_t bytes_transferred = 0;
  654. sr.split(false);
  655. for(;;)
  656. {
  657. bytes_transferred +=
  658. write_some(stream, sr, ec);
  659. if(ec)
  660. return bytes_transferred;
  661. if(sr.is_done())
  662. break;
  663. }
  664. return bytes_transferred;
  665. }
  666. template<
  667. class AsyncWriteStream,
  668. bool isRequest, class Body, class Fields,
  669. BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
  670. BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
  671. async_write(
  672. AsyncWriteStream& stream,
  673. serializer<isRequest, Body, Fields>& sr,
  674. WriteHandler&& handler)
  675. {
  676. static_assert(is_async_write_stream<
  677. AsyncWriteStream>::value,
  678. "AsyncWriteStream type requirements not met");
  679. static_assert(is_body<Body>::value,
  680. "Body type requirements not met");
  681. static_assert(is_body_writer<Body>::value,
  682. "BodyWriter type requirements not met");
  683. sr.split(false);
  684. return net::async_initiate<
  685. WriteHandler,
  686. void(error_code, std::size_t)>(
  687. detail::run_write_op<AsyncWriteStream>{&stream},
  688. handler,
  689. detail::serializer_is_done{},
  690. &sr);
  691. }
  692. //------------------------------------------------------------------------------
  693. template<
  694. class SyncWriteStream,
  695. bool isRequest, class Body, class Fields>
  696. typename std::enable_if<
  697. is_mutable_body_writer<Body>::value,
  698. std::size_t>::type
  699. write(
  700. SyncWriteStream& stream,
  701. message<isRequest, Body, Fields>& msg)
  702. {
  703. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  704. "SyncWriteStream type requirements not met");
  705. static_assert(is_body<Body>::value,
  706. "Body type requirements not met");
  707. static_assert(is_body_writer<Body>::value,
  708. "BodyWriter type requirements not met");
  709. error_code ec;
  710. auto const bytes_transferred =
  711. write(stream, msg, ec);
  712. if(ec)
  713. BOOST_THROW_EXCEPTION(system_error{ec});
  714. return bytes_transferred;
  715. }
  716. template<
  717. class SyncWriteStream,
  718. bool isRequest, class Body, class Fields>
  719. typename std::enable_if<
  720. ! is_mutable_body_writer<Body>::value,
  721. std::size_t>::type
  722. write(
  723. SyncWriteStream& stream,
  724. message<isRequest, Body, Fields> const& msg)
  725. {
  726. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  727. "SyncWriteStream type requirements not met");
  728. static_assert(is_body<Body>::value,
  729. "Body type requirements not met");
  730. static_assert(is_body_writer<Body>::value,
  731. "BodyWriter type requirements not met");
  732. error_code ec;
  733. auto const bytes_transferred =
  734. write(stream, msg, ec);
  735. if(ec)
  736. BOOST_THROW_EXCEPTION(system_error{ec});
  737. return bytes_transferred;
  738. }
  739. template<
  740. class SyncWriteStream,
  741. bool isRequest, class Body, class Fields>
  742. typename std::enable_if<
  743. is_mutable_body_writer<Body>::value,
  744. std::size_t>::type
  745. write(
  746. SyncWriteStream& stream,
  747. message<isRequest, Body, Fields>& msg,
  748. error_code& ec)
  749. {
  750. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  751. "SyncWriteStream type requirements not met");
  752. static_assert(is_body<Body>::value,
  753. "Body type requirements not met");
  754. static_assert(is_body_writer<Body>::value,
  755. "BodyWriter type requirements not met");
  756. serializer<isRequest, Body, Fields> sr{msg};
  757. return write(stream, sr, ec);
  758. }
  759. template<
  760. class SyncWriteStream,
  761. bool isRequest, class Body, class Fields>
  762. typename std::enable_if<
  763. ! is_mutable_body_writer<Body>::value,
  764. std::size_t>::type
  765. write(
  766. SyncWriteStream& stream,
  767. message<isRequest, Body, Fields> const& msg,
  768. error_code& ec)
  769. {
  770. static_assert(is_sync_write_stream<SyncWriteStream>::value,
  771. "SyncWriteStream type requirements not met");
  772. static_assert(is_body<Body>::value,
  773. "Body type requirements not met");
  774. static_assert(is_body_writer<Body>::value,
  775. "BodyWriter type requirements not met");
  776. serializer<isRequest, Body, Fields> sr{msg};
  777. return write(stream, sr, ec);
  778. }
  779. template<
  780. class AsyncWriteStream,
  781. bool isRequest, class Body, class Fields,
  782. BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
  783. BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
  784. async_write(
  785. AsyncWriteStream& stream,
  786. message<isRequest, Body, Fields>& msg,
  787. WriteHandler&& handler,
  788. typename std::enable_if<
  789. is_mutable_body_writer<Body>::value>::type*)
  790. {
  791. static_assert(
  792. is_async_write_stream<AsyncWriteStream>::value,
  793. "AsyncWriteStream type requirements not met");
  794. static_assert(is_body<Body>::value,
  795. "Body type requirements not met");
  796. static_assert(is_body_writer<Body>::value,
  797. "BodyWriter type requirements not met");
  798. return net::async_initiate<
  799. WriteHandler,
  800. void(error_code, std::size_t)>(
  801. detail::run_write_msg_op<AsyncWriteStream>{&stream},
  802. handler,
  803. &msg,
  804. std::false_type{});
  805. }
  806. template<
  807. class AsyncWriteStream,
  808. bool isRequest, class Body, class Fields,
  809. BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
  810. BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
  811. async_write(
  812. AsyncWriteStream& stream,
  813. message<isRequest, Body, Fields> const& msg,
  814. WriteHandler&& handler,
  815. typename std::enable_if<
  816. ! is_mutable_body_writer<Body>::value>::type*)
  817. {
  818. static_assert(
  819. is_async_write_stream<AsyncWriteStream>::value,
  820. "AsyncWriteStream type requirements not met");
  821. static_assert(is_body<Body>::value,
  822. "Body type requirements not met");
  823. static_assert(is_body_writer<Body>::value,
  824. "BodyWriter type requirements not met");
  825. return net::async_initiate<
  826. WriteHandler,
  827. void(error_code, std::size_t)>(
  828. detail::run_write_msg_op<AsyncWriteStream>{&stream},
  829. handler,
  830. &msg,
  831. std::true_type{});
  832. }
  833. //------------------------------------------------------------------------------
  834. namespace detail {
  835. template<class Serializer>
  836. class write_ostream_lambda
  837. {
  838. std::ostream& os_;
  839. Serializer& sr_;
  840. public:
  841. write_ostream_lambda(std::ostream& os,
  842. Serializer& sr)
  843. : os_(os)
  844. , sr_(sr)
  845. {
  846. }
  847. template<class ConstBufferSequence>
  848. void
  849. operator()(error_code& ec,
  850. ConstBufferSequence const& buffers) const
  851. {
  852. ec = {};
  853. if(os_.fail())
  854. return;
  855. std::size_t bytes_transferred = 0;
  856. for(auto b : beast::buffers_range_ref(buffers))
  857. {
  858. os_.write(static_cast<char const*>(
  859. b.data()), b.size());
  860. if(os_.fail())
  861. return;
  862. bytes_transferred += b.size();
  863. }
  864. sr_.consume(bytes_transferred);
  865. }
  866. };
  867. } // detail
  868. template<class Fields>
  869. std::ostream&
  870. operator<<(std::ostream& os,
  871. header<true, Fields> const& h)
  872. {
  873. typename Fields::writer fr{
  874. h, h.version(), h.method()};
  875. return os << beast::make_printable(fr.get());
  876. }
  877. template<class Fields>
  878. std::ostream&
  879. operator<<(std::ostream& os,
  880. header<false, Fields> const& h)
  881. {
  882. typename Fields::writer fr{
  883. h, h.version(), h.result_int()};
  884. return os << beast::make_printable(fr.get());
  885. }
  886. template<bool isRequest, class Body, class Fields>
  887. std::ostream&
  888. operator<<(std::ostream& os,
  889. message<isRequest, Body, Fields> const& msg)
  890. {
  891. static_assert(is_body<Body>::value,
  892. "Body type requirements not met");
  893. static_assert(is_body_writer<Body>::value,
  894. "BodyWriter type requirements not met");
  895. serializer<isRequest, Body, Fields> sr{msg};
  896. error_code ec;
  897. detail::write_ostream_lambda<decltype(sr)> f{os, sr};
  898. do
  899. {
  900. sr.next(ec, f);
  901. if(os.fail())
  902. break;
  903. if(ec)
  904. {
  905. os.setstate(std::ios::failbit);
  906. break;
  907. }
  908. }
  909. while(! sr.is_done());
  910. return os;
  911. }
  912. } // http
  913. } // beast
  914. } // boost
  915. #endif