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