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