File indexing completed on 2025-01-18 09:29:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_HTTP_IMPL_WRITE_HPP
0011 #define BOOST_BEAST_HTTP_IMPL_WRITE_HPP
0012
0013 #include <boost/beast/http/type_traits.hpp>
0014 #include <boost/beast/core/async_base.hpp>
0015 #include <boost/beast/core/bind_handler.hpp>
0016 #include <boost/beast/core/buffers_range.hpp>
0017 #include <boost/beast/core/make_printable.hpp>
0018 #include <boost/beast/core/stream_traits.hpp>
0019 #include <boost/beast/core/detail/is_invocable.hpp>
0020 #include <boost/asio/coroutine.hpp>
0021 #include <boost/asio/dispatch.hpp>
0022 #include <boost/asio/write.hpp>
0023 #include <boost/optional.hpp>
0024 #include <boost/throw_exception.hpp>
0025 #include <ostream>
0026 #include <sstream>
0027
0028 namespace boost {
0029 namespace beast {
0030 namespace http {
0031 namespace detail {
0032
0033 template<
0034 class Handler,
0035 class Stream,
0036 bool isRequest, class Body, class Fields>
0037 class write_some_op
0038 : public beast::async_base<
0039 Handler, beast::executor_type<Stream>>
0040 {
0041 Stream& s_;
0042 serializer<isRequest,Body, Fields>& sr_;
0043
0044 class lambda
0045 {
0046 write_some_op& op_;
0047
0048 public:
0049 bool invoked = false;
0050
0051 explicit
0052 lambda(write_some_op& op)
0053 : op_(op)
0054 {
0055 }
0056
0057 template<class ConstBufferSequence>
0058 void
0059 operator()(
0060 error_code& ec,
0061 ConstBufferSequence const& buffers)
0062 {
0063 BOOST_ASIO_HANDLER_LOCATION((
0064 __FILE__, __LINE__,
0065 "http::async_write_some"));
0066
0067 invoked = true;
0068 ec = {};
0069 op_.s_.async_write_some(
0070 buffers, std::move(op_));
0071 }
0072 };
0073
0074 public:
0075 template<class Handler_>
0076 write_some_op(
0077 Handler_&& h,
0078 Stream& s,
0079 serializer<isRequest, Body, Fields>& sr)
0080 : async_base<
0081 Handler, beast::executor_type<Stream>>(
0082 std::forward<Handler_>(h), s.get_executor())
0083 , s_(s)
0084 , sr_(sr)
0085 {
0086 (*this)();
0087 }
0088
0089 void
0090 operator()()
0091 {
0092 error_code ec;
0093 if(! sr_.is_done())
0094 {
0095 lambda f{*this};
0096 sr_.next(ec, f);
0097 if(ec)
0098 {
0099 BOOST_ASSERT(! f.invoked);
0100
0101 BOOST_ASIO_HANDLER_LOCATION((
0102 __FILE__, __LINE__,
0103 "http::async_write_some"));
0104
0105 auto ex = asio::get_associated_immediate_executor(*this, s_.get_executor());
0106 return net::dispatch(
0107 ex,
0108 beast::bind_front_handler(
0109 std::move(*this), ec, 0));
0110 }
0111 if(f.invoked)
0112 {
0113
0114 return;
0115 }
0116
0117 BOOST_ASSERT(sr_.is_done());
0118 }
0119
0120 BOOST_ASIO_HANDLER_LOCATION((
0121 __FILE__, __LINE__,
0122 "http::async_write_some"));
0123
0124 const auto ex = this->get_immediate_executor();
0125 return net::dispatch(
0126 ex,
0127 beast::bind_front_handler(
0128 std::move(*this), ec, 0));
0129 }
0130
0131 void
0132 operator()(
0133 error_code ec,
0134 std::size_t bytes_transferred)
0135 {
0136 if(! ec)
0137 sr_.consume(bytes_transferred);
0138 this->complete_now(ec, bytes_transferred);
0139 }
0140 };
0141
0142
0143
0144 struct serializer_is_header_done
0145 {
0146 template<
0147 bool isRequest, class Body, class Fields>
0148 bool
0149 operator()(
0150 serializer<isRequest, Body, Fields>& sr) const
0151 {
0152 return sr.is_header_done();
0153 }
0154 };
0155
0156 struct serializer_is_done
0157 {
0158 template<
0159 bool isRequest, class Body, class Fields>
0160 bool
0161 operator()(
0162 serializer<isRequest, Body, Fields>& sr) const
0163 {
0164 return sr.is_done();
0165 }
0166 };
0167
0168
0169
0170 template<
0171 class Handler,
0172 class Stream,
0173 class Predicate,
0174 bool isRequest, class Body, class Fields>
0175 class write_op
0176 : public beast::async_base<
0177 Handler, beast::executor_type<Stream>>
0178 , public asio::coroutine
0179 {
0180 Stream& s_;
0181 serializer<isRequest, Body, Fields>& sr_;
0182 std::size_t bytes_transferred_ = 0;
0183 net::cancellation_state st_{this->
0184 beast::async_base<Handler, beast::executor_type<Stream>>
0185 ::get_cancellation_slot()};
0186
0187 public:
0188 using cancellation_slot_type = net::cancellation_slot;
0189 cancellation_slot_type get_cancellation_slot() const noexcept
0190 {
0191 return st_.slot();
0192 }
0193
0194
0195 template<class Handler_>
0196 write_op(
0197 Handler_&& h,
0198 Stream& s,
0199 serializer<isRequest, Body, Fields>& sr)
0200 : async_base<
0201 Handler, beast::executor_type<Stream>>(
0202 std::forward<Handler_>(h), s.get_executor())
0203 , s_(s)
0204 , sr_(sr)
0205 {
0206 (*this)();
0207 }
0208
0209 void
0210 operator()(
0211 error_code ec = {},
0212 std::size_t bytes_transferred = 0)
0213 {
0214 BOOST_ASIO_CORO_REENTER(*this)
0215 {
0216 if(Predicate{}(sr_))
0217 {
0218 BOOST_ASIO_CORO_YIELD
0219 {
0220 BOOST_ASIO_HANDLER_LOCATION((
0221 __FILE__, __LINE__,
0222 "http::async_write"));
0223
0224 const auto ex = this->get_immediate_executor();
0225 net::dispatch(
0226 ex,
0227 std::move(*this));
0228 }
0229 goto upcall;
0230 }
0231 for(;;)
0232 {
0233 BOOST_ASIO_CORO_YIELD
0234 {
0235 BOOST_ASIO_HANDLER_LOCATION((
0236 __FILE__, __LINE__,
0237 "http::async_write"));
0238
0239 beast::http::async_write_some(
0240 s_, sr_, std::move(*this));
0241 }
0242 bytes_transferred_ += bytes_transferred;
0243 if (!ec && st_.cancelled() != net::cancellation_type::none)
0244 {
0245 BOOST_BEAST_ASSIGN_EC(ec, net::error::operation_aborted);
0246 }
0247 if(ec)
0248 goto upcall;
0249 if(Predicate{}(sr_))
0250 break;
0251 }
0252 upcall:
0253 this->complete_now(ec, bytes_transferred_);
0254 }
0255 }
0256 };
0257
0258
0259
0260 template<
0261 class Handler,
0262 class Stream,
0263 bool isRequest, class Body, class Fields>
0264 class write_msg_op
0265 : public beast::stable_async_base<
0266 Handler, beast::executor_type<Stream>>
0267 {
0268 Stream& s_;
0269 serializer<isRequest, Body, Fields>& sr_;
0270
0271 public:
0272 template<
0273 class Handler_,
0274 class... Args>
0275 write_msg_op(
0276 Handler_&& h,
0277 Stream& s,
0278 Args&&... args)
0279 : stable_async_base<
0280 Handler, beast::executor_type<Stream>>(
0281 std::forward<Handler_>(h), s.get_executor())
0282 , s_(s)
0283 , sr_(beast::allocate_stable<
0284 serializer<isRequest, Body, Fields>>(
0285 *this, std::forward<Args>(args)...))
0286 {
0287 (*this)();
0288 }
0289
0290 void
0291 operator()()
0292 {
0293 BOOST_ASIO_HANDLER_LOCATION((
0294 __FILE__, __LINE__,
0295 "http::async_write(msg)"));
0296
0297 async_write(s_, sr_, std::move(*this));
0298 }
0299
0300 void
0301 operator()(
0302 error_code ec, std::size_t bytes_transferred)
0303 {
0304 this->complete_now(ec, bytes_transferred);
0305 }
0306 };
0307
0308 struct run_write_some_op
0309 {
0310 template<
0311 class WriteHandler,
0312 class Stream,
0313 bool isRequest, class Body, class Fields>
0314 void
0315 operator()(
0316 WriteHandler&& h,
0317 Stream* s,
0318 serializer<isRequest, Body, Fields>* sr)
0319 {
0320
0321
0322
0323
0324 static_assert(
0325 beast::detail::is_invocable<WriteHandler,
0326 void(error_code, std::size_t)>::value,
0327 "WriteHandler type requirements not met");
0328
0329 write_some_op<
0330 typename std::decay<WriteHandler>::type,
0331 Stream,
0332 isRequest, Body, Fields>(
0333 std::forward<WriteHandler>(h), *s, *sr);
0334 }
0335 };
0336
0337 struct run_write_op
0338 {
0339 template<
0340 class WriteHandler,
0341 class Stream,
0342 class Predicate,
0343 bool isRequest, class Body, class Fields>
0344 void
0345 operator()(
0346 WriteHandler&& h,
0347 Stream* s,
0348 Predicate const&,
0349 serializer<isRequest, Body, Fields>* sr)
0350 {
0351
0352
0353
0354
0355 static_assert(
0356 beast::detail::is_invocable<WriteHandler,
0357 void(error_code, std::size_t)>::value,
0358 "WriteHandler type requirements not met");
0359
0360 write_op<
0361 typename std::decay<WriteHandler>::type,
0362 Stream,
0363 Predicate,
0364 isRequest, Body, Fields>(
0365 std::forward<WriteHandler>(h), *s, *sr);
0366 }
0367 };
0368
0369 struct run_write_msg_op
0370 {
0371 template<
0372 class WriteHandler,
0373 class Stream,
0374 bool isRequest, class Body, class Fields,
0375 class... Args>
0376 void
0377 operator()(
0378 WriteHandler&& h,
0379 Stream* s,
0380 message<isRequest, Body, Fields>* m,
0381 std::false_type,
0382 Args&&... args)
0383 {
0384
0385
0386
0387
0388 static_assert(
0389 beast::detail::is_invocable<WriteHandler,
0390 void(error_code, std::size_t)>::value,
0391 "WriteHandler type requirements not met");
0392
0393 write_msg_op<
0394 typename std::decay<WriteHandler>::type,
0395 Stream,
0396 isRequest, Body, Fields>(
0397 std::forward<WriteHandler>(h), *s, *m,
0398 std::forward<Args>(args)...);
0399 }
0400
0401 template<
0402 class WriteHandler,
0403 class Stream,
0404 bool isRequest, class Body, class Fields,
0405 class... Args>
0406 void
0407 operator()(
0408 WriteHandler&& h,
0409 Stream* s,
0410 message<isRequest, Body, Fields> const* m,
0411 std::true_type,
0412 Args&&... args)
0413 {
0414
0415
0416
0417
0418 static_assert(
0419 beast::detail::is_invocable<WriteHandler,
0420 void(error_code, std::size_t)>::value,
0421 "WriteHandler type requirements not met");
0422
0423 write_msg_op<
0424 typename std::decay<WriteHandler>::type,
0425 Stream,
0426 isRequest, Body, Fields>(
0427 std::forward<WriteHandler>(h), *s, *m,
0428 std::forward<Args>(args)...);
0429 }
0430 };
0431
0432
0433
0434 template<class Stream>
0435 class write_some_lambda
0436 {
0437 Stream& stream_;
0438
0439 public:
0440 bool invoked = false;
0441 std::size_t bytes_transferred = 0;
0442
0443 explicit
0444 write_some_lambda(Stream& stream)
0445 : stream_(stream)
0446 {
0447 }
0448
0449 template<class ConstBufferSequence>
0450 void
0451 operator()(error_code& ec,
0452 ConstBufferSequence const& buffers)
0453 {
0454 invoked = true;
0455 bytes_transferred =
0456 stream_.write_some(buffers, ec);
0457 }
0458 };
0459
0460 template<class Stream>
0461 class write_lambda
0462 {
0463 Stream& stream_;
0464
0465 public:
0466 bool invoked = false;
0467 std::size_t bytes_transferred = 0;
0468
0469 explicit
0470 write_lambda(Stream& stream)
0471 : stream_(stream)
0472 {
0473 }
0474
0475 template<class ConstBufferSequence>
0476 void
0477 operator()(error_code& ec,
0478 ConstBufferSequence const& buffers)
0479 {
0480 invoked = true;
0481 bytes_transferred = net::write(
0482 stream_, buffers, ec);
0483 }
0484 };
0485
0486 template<
0487 class SyncWriteStream,
0488 bool isRequest, class Body, class Fields>
0489 std::size_t
0490 write_some_impl(
0491 SyncWriteStream& stream,
0492 serializer<isRequest, Body, Fields>& sr,
0493 error_code& ec)
0494 {
0495 if(! sr.is_done())
0496 {
0497 write_some_lambda<SyncWriteStream> f{stream};
0498 sr.next(ec, f);
0499 if(ec)
0500 return f.bytes_transferred;
0501 if(f.invoked)
0502 sr.consume(f.bytes_transferred);
0503 return f.bytes_transferred;
0504 }
0505 ec = {};
0506 return 0;
0507 }
0508
0509 template<
0510 class AsyncWriteStream,
0511 bool isRequest, class Body, class Fields,
0512 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0513 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0514 async_write_some_impl(
0515 AsyncWriteStream& stream,
0516 serializer<isRequest, Body, Fields>& sr,
0517 WriteHandler&& handler)
0518 {
0519 return net::async_initiate<
0520 WriteHandler,
0521 void(error_code, std::size_t)>(
0522 run_write_some_op{},
0523 handler,
0524 &stream,
0525 &sr);
0526 }
0527
0528 }
0529
0530
0531
0532 template<
0533 class SyncWriteStream,
0534 bool isRequest, class Body, class Fields>
0535 std::size_t
0536 write_some(
0537 SyncWriteStream& stream,
0538 serializer<isRequest, Body, Fields>& sr)
0539 {
0540 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0541 "SyncWriteStream type requirements not met");
0542 static_assert(is_body<Body>::value,
0543 "Body type requirements not met");
0544 static_assert(is_body_writer<Body>::value,
0545 "BodyWriter type requirements not met");
0546 error_code ec;
0547 auto const bytes_transferred =
0548 write_some(stream, sr, ec);
0549 if(ec)
0550 BOOST_THROW_EXCEPTION(system_error{ec});
0551 return bytes_transferred;
0552 }
0553
0554 template<
0555 class SyncWriteStream,
0556 bool isRequest, class Body, class Fields>
0557 std::size_t
0558 write_some(
0559 SyncWriteStream& stream,
0560 serializer<isRequest, Body, Fields>& sr,
0561 error_code& ec)
0562 {
0563 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0564 "SyncWriteStream type requirements not met");
0565 static_assert(is_body<Body>::value,
0566 "Body type requirements not met");
0567 static_assert(is_body_writer<Body>::value,
0568 "BodyWriter type requirements not met");
0569 return detail::write_some_impl(stream, sr, ec);
0570 }
0571
0572 template<
0573 class AsyncWriteStream,
0574 bool isRequest, class Body, class Fields,
0575 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0576 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0577 async_write_some(
0578 AsyncWriteStream& stream,
0579 serializer<isRequest, Body, Fields>& sr,
0580 WriteHandler&& handler)
0581 {
0582 static_assert(is_async_write_stream<
0583 AsyncWriteStream>::value,
0584 "AsyncWriteStream type requirements not met");
0585 static_assert(is_body<Body>::value,
0586 "Body type requirements not met");
0587 static_assert(is_body_writer<Body>::value,
0588 "BodyWriter type requirements not met");
0589 return detail::async_write_some_impl(stream, sr,
0590 std::forward<WriteHandler>(handler));
0591 }
0592
0593
0594
0595 template<
0596 class SyncWriteStream,
0597 bool isRequest, class Body, class Fields>
0598 std::size_t
0599 write_header(SyncWriteStream& stream,
0600 serializer<isRequest, Body, Fields>& sr)
0601 {
0602 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0603 "SyncWriteStream type requirements not met");
0604 static_assert(is_body<Body>::value,
0605 "Body type requirements not met");
0606 static_assert(is_body_writer<Body>::value,
0607 "BodyWriter type requirements not met");
0608 error_code ec;
0609 auto const bytes_transferred =
0610 write_header(stream, sr, ec);
0611 if(ec)
0612 BOOST_THROW_EXCEPTION(system_error{ec});
0613 return bytes_transferred;
0614 }
0615
0616 template<
0617 class SyncWriteStream,
0618 bool isRequest, class Body, class Fields>
0619 std::size_t
0620 write_header(
0621 SyncWriteStream& stream,
0622 serializer<isRequest, Body, Fields>& sr,
0623 error_code& ec)
0624 {
0625 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0626 "SyncWriteStream type requirements not met");
0627 static_assert(is_body<Body>::value,
0628 "Body type requirements not met");
0629 static_assert(is_body_writer<Body>::value,
0630 "BodyWriter type requirements not met");
0631 sr.split(true);
0632 std::size_t bytes_transferred = 0;
0633 if(! sr.is_header_done())
0634 {
0635 detail::write_lambda<SyncWriteStream> f{stream};
0636 do
0637 {
0638 sr.next(ec, f);
0639 bytes_transferred += f.bytes_transferred;
0640 if(ec)
0641 return bytes_transferred;
0642 BOOST_ASSERT(f.invoked);
0643 sr.consume(f.bytes_transferred);
0644 }
0645 while(! sr.is_header_done());
0646 }
0647 else
0648 {
0649 ec = {};
0650 }
0651 return bytes_transferred;
0652 }
0653
0654 template<
0655 class AsyncWriteStream,
0656 bool isRequest, class Body, class Fields,
0657 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0658 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0659 async_write_header(
0660 AsyncWriteStream& stream,
0661 serializer<isRequest, Body, Fields>& sr,
0662 WriteHandler&& handler)
0663 {
0664 static_assert(is_async_write_stream<
0665 AsyncWriteStream>::value,
0666 "AsyncWriteStream type requirements not met");
0667 static_assert(is_body<Body>::value,
0668 "Body type requirements not met");
0669 static_assert(is_body_writer<Body>::value,
0670 "BodyWriter type requirements not met");
0671 sr.split(true);
0672 return net::async_initiate<
0673 WriteHandler,
0674 void(error_code, std::size_t)>(
0675 detail::run_write_op{},
0676 handler,
0677 &stream,
0678 detail::serializer_is_header_done{},
0679 &sr);
0680 }
0681
0682
0683
0684 template<
0685 class SyncWriteStream,
0686 bool isRequest, class Body, class Fields>
0687 std::size_t
0688 write(
0689 SyncWriteStream& stream,
0690 serializer<isRequest, Body, Fields>& sr)
0691 {
0692 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0693 "SyncWriteStream type requirements not met");
0694 error_code ec;
0695 auto const bytes_transferred =
0696 write(stream, sr, ec);
0697 if(ec)
0698 BOOST_THROW_EXCEPTION(system_error{ec});
0699 return bytes_transferred;
0700 }
0701
0702 template<
0703 class SyncWriteStream,
0704 bool isRequest, class Body, class Fields>
0705 std::size_t
0706 write(
0707 SyncWriteStream& stream,
0708 serializer<isRequest, Body, Fields>& sr,
0709 error_code& ec)
0710 {
0711 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0712 "SyncWriteStream type requirements not met");
0713 std::size_t bytes_transferred = 0;
0714 sr.split(false);
0715 for(;;)
0716 {
0717 bytes_transferred +=
0718 write_some(stream, sr, ec);
0719 if(ec)
0720 return bytes_transferred;
0721 if(sr.is_done())
0722 break;
0723 }
0724 return bytes_transferred;
0725 }
0726
0727 template<
0728 class AsyncWriteStream,
0729 bool isRequest, class Body, class Fields,
0730 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0731 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0732 async_write(
0733 AsyncWriteStream& stream,
0734 serializer<isRequest, Body, Fields>& sr,
0735 WriteHandler&& handler)
0736 {
0737 static_assert(is_async_write_stream<
0738 AsyncWriteStream>::value,
0739 "AsyncWriteStream type requirements not met");
0740 static_assert(is_body<Body>::value,
0741 "Body type requirements not met");
0742 static_assert(is_body_writer<Body>::value,
0743 "BodyWriter type requirements not met");
0744 sr.split(false);
0745 return net::async_initiate<
0746 WriteHandler,
0747 void(error_code, std::size_t)>(
0748 detail::run_write_op{},
0749 handler,
0750 &stream,
0751 detail::serializer_is_done{},
0752 &sr);
0753 }
0754
0755
0756
0757 template<
0758 class SyncWriteStream,
0759 bool isRequest, class Body, class Fields>
0760 typename std::enable_if<
0761 is_mutable_body_writer<Body>::value,
0762 std::size_t>::type
0763 write(
0764 SyncWriteStream& stream,
0765 message<isRequest, Body, Fields>& msg)
0766 {
0767 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0768 "SyncWriteStream type requirements not met");
0769 static_assert(is_body<Body>::value,
0770 "Body type requirements not met");
0771 static_assert(is_body_writer<Body>::value,
0772 "BodyWriter type requirements not met");
0773 error_code ec;
0774 auto const bytes_transferred =
0775 write(stream, msg, ec);
0776 if(ec)
0777 BOOST_THROW_EXCEPTION(system_error{ec});
0778 return bytes_transferred;
0779 }
0780
0781 template<
0782 class SyncWriteStream,
0783 bool isRequest, class Body, class Fields>
0784 typename std::enable_if<
0785 ! is_mutable_body_writer<Body>::value,
0786 std::size_t>::type
0787 write(
0788 SyncWriteStream& stream,
0789 message<isRequest, Body, Fields> const& msg)
0790 {
0791 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0792 "SyncWriteStream type requirements not met");
0793 static_assert(is_body<Body>::value,
0794 "Body type requirements not met");
0795 static_assert(is_body_writer<Body>::value,
0796 "BodyWriter type requirements not met");
0797 error_code ec;
0798 auto const bytes_transferred =
0799 write(stream, msg, ec);
0800 if(ec)
0801 BOOST_THROW_EXCEPTION(system_error{ec});
0802 return bytes_transferred;
0803 }
0804
0805 template<
0806 class SyncWriteStream,
0807 bool isRequest, class Body, class Fields>
0808 typename std::enable_if<
0809 is_mutable_body_writer<Body>::value,
0810 std::size_t>::type
0811 write(
0812 SyncWriteStream& stream,
0813 message<isRequest, Body, Fields>& msg,
0814 error_code& ec)
0815 {
0816 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0817 "SyncWriteStream type requirements not met");
0818 static_assert(is_body<Body>::value,
0819 "Body type requirements not met");
0820 static_assert(is_body_writer<Body>::value,
0821 "BodyWriter type requirements not met");
0822 serializer<isRequest, Body, Fields> sr{msg};
0823 return write(stream, sr, ec);
0824 }
0825
0826 template<
0827 class SyncWriteStream,
0828 bool isRequest, class Body, class Fields>
0829 typename std::enable_if<
0830 ! is_mutable_body_writer<Body>::value,
0831 std::size_t>::type
0832 write(
0833 SyncWriteStream& stream,
0834 message<isRequest, Body, Fields> const& msg,
0835 error_code& ec)
0836 {
0837 static_assert(is_sync_write_stream<SyncWriteStream>::value,
0838 "SyncWriteStream type requirements not met");
0839 static_assert(is_body<Body>::value,
0840 "Body type requirements not met");
0841 static_assert(is_body_writer<Body>::value,
0842 "BodyWriter type requirements not met");
0843 serializer<isRequest, Body, Fields> sr{msg};
0844 return write(stream, sr, ec);
0845 }
0846
0847 template<
0848 class AsyncWriteStream,
0849 bool isRequest, class Body, class Fields,
0850 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0851 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0852 async_write(
0853 AsyncWriteStream& stream,
0854 message<isRequest, Body, Fields>& msg,
0855 WriteHandler&& handler,
0856 typename std::enable_if<
0857 is_mutable_body_writer<Body>::value>::type*)
0858 {
0859 static_assert(
0860 is_async_write_stream<AsyncWriteStream>::value,
0861 "AsyncWriteStream type requirements not met");
0862 static_assert(is_body<Body>::value,
0863 "Body type requirements not met");
0864 static_assert(is_body_writer<Body>::value,
0865 "BodyWriter type requirements not met");
0866 return net::async_initiate<
0867 WriteHandler,
0868 void(error_code, std::size_t)>(
0869 detail::run_write_msg_op{},
0870 handler,
0871 &stream,
0872 &msg,
0873 std::false_type{});
0874 }
0875
0876 template<
0877 class AsyncWriteStream,
0878 bool isRequest, class Body, class Fields,
0879 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
0880 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0881 async_write(
0882 AsyncWriteStream& stream,
0883 message<isRequest, Body, Fields> const& msg,
0884 WriteHandler&& handler,
0885 typename std::enable_if<
0886 ! is_mutable_body_writer<Body>::value>::type*)
0887 {
0888 static_assert(
0889 is_async_write_stream<AsyncWriteStream>::value,
0890 "AsyncWriteStream type requirements not met");
0891 static_assert(is_body<Body>::value,
0892 "Body type requirements not met");
0893 static_assert(is_body_writer<Body>::value,
0894 "BodyWriter type requirements not met");
0895 return net::async_initiate<
0896 WriteHandler,
0897 void(error_code, std::size_t)>(
0898 detail::run_write_msg_op{},
0899 handler,
0900 &stream,
0901 &msg,
0902 std::true_type{});
0903 }
0904
0905
0906
0907 namespace detail {
0908
0909 template<class Serializer>
0910 class write_ostream_lambda
0911 {
0912 std::ostream& os_;
0913 Serializer& sr_;
0914
0915 public:
0916 write_ostream_lambda(std::ostream& os,
0917 Serializer& sr)
0918 : os_(os)
0919 , sr_(sr)
0920 {
0921 }
0922
0923 template<class ConstBufferSequence>
0924 void
0925 operator()(error_code& ec,
0926 ConstBufferSequence const& buffers) const
0927 {
0928 ec = {};
0929 if(os_.fail())
0930 return;
0931 std::size_t bytes_transferred = 0;
0932 for(auto b : beast::buffers_range_ref(buffers))
0933 {
0934 os_.write(static_cast<char const*>(
0935 b.data()), b.size());
0936 if(os_.fail())
0937 return;
0938 bytes_transferred += b.size();
0939 }
0940 sr_.consume(bytes_transferred);
0941 }
0942 };
0943
0944 }
0945
0946 template<class Fields>
0947 std::ostream&
0948 operator<<(std::ostream& os,
0949 header<true, Fields> const& h)
0950 {
0951 typename Fields::writer fr{
0952 h, h.version(), h.method()};
0953 return os << beast::make_printable(fr.get());
0954 }
0955
0956 template<class Fields>
0957 std::ostream&
0958 operator<<(std::ostream& os,
0959 header<false, Fields> const& h)
0960 {
0961 typename Fields::writer fr{
0962 h, h.version(), h.result_int()};
0963 return os << beast::make_printable(fr.get());
0964 }
0965
0966 template<bool isRequest, class Body, class Fields>
0967 std::ostream&
0968 operator<<(std::ostream& os,
0969 message<isRequest, Body, Fields> const& msg)
0970 {
0971 static_assert(is_body<Body>::value,
0972 "Body type requirements not met");
0973 static_assert(is_body_writer<Body>::value,
0974 "BodyWriter type requirements not met");
0975 serializer<isRequest, Body, Fields> sr{msg};
0976 error_code ec;
0977 detail::write_ostream_lambda<decltype(sr)> f{os, sr};
0978 do
0979 {
0980 sr.next(ec, f);
0981 if(os.fail())
0982 break;
0983 if(ec)
0984 {
0985 os.setstate(std::ios::failbit);
0986 break;
0987 }
0988 }
0989 while(! sr.is_done());
0990 return os;
0991 }
0992
0993 }
0994 }
0995 }
0996
0997 #endif