write.hpp 27 KB

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