2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_HTTP_IMPL_WRITE_HPP
11 #define BOOST_BEAST_HTTP_IMPL_WRITE_HPP
13 #include <boost/beast/http/type_traits.hpp>
14 #include <boost/beast/core/async_base.hpp>
15 #include <boost/beast/core/bind_handler.hpp>
16 #include <boost/beast/core/buffers_range.hpp>
17 #include <boost/beast/core/make_printable.hpp>
18 #include <boost/beast/core/stream_traits.hpp>
19 #include <boost/beast/core/detail/is_invocable.hpp>
20 #include <boost/asio/coroutine.hpp>
21 #include <boost/asio/post.hpp>
22 #include <boost/asio/write.hpp>
23 #include <boost/optional.hpp>
24 #include <boost/throw_exception.hpp>
36 bool isRequest, class Body, class Fields>
38 : public beast::async_base<
39 Handler, beast::executor_type<Stream>>
42 serializer<isRequest,Body, Fields>& sr_;
52 lambda(write_some_op& op)
57 template<class ConstBufferSequence>
61 ConstBufferSequence const& buffers)
65 op_.s_.async_write_some(
66 buffers, std::move(op_));
71 template<class Handler_>
75 serializer<isRequest, Body, Fields>& sr)
77 Handler, beast::executor_type<Stream>>(
78 std::forward<Handler_>(h), s.get_executor())
95 BOOST_ASSERT(! f.invoked);
98 beast::bind_front_handler(
99 std::move(*this), ec, 0));
103 // *this is now moved-from,
106 // What else could it be?
107 BOOST_ASSERT(sr_.is_done());
112 beast::bind_front_handler(
113 std::move(*this), ec, 0));
119 std::size_t bytes_transferred)
122 sr_.consume(bytes_transferred);
123 this->complete_now(ec, bytes_transferred);
127 //------------------------------------------------------------------------------
129 struct serializer_is_header_done
132 bool isRequest, class Body, class Fields>
135 serializer<isRequest, Body, Fields>& sr) const
137 return sr.is_header_done();
141 struct serializer_is_done
144 bool isRequest, class Body, class Fields>
147 serializer<isRequest, Body, Fields>& sr) const
153 //------------------------------------------------------------------------------
159 bool isRequest, class Body, class Fields>
161 : public beast::async_base<
162 Handler, beast::executor_type<Stream>>
163 , public asio::coroutine
166 serializer<isRequest, Body, Fields>& sr_;
167 std::size_t bytes_transferred_ = 0;
170 template<class Handler_>
174 serializer<isRequest, Body, Fields>& sr)
176 Handler, beast::executor_type<Stream>>(
177 std::forward<Handler_>(h), s.get_executor())
187 std::size_t bytes_transferred = 0)
189 BOOST_ASIO_CORO_REENTER(*this)
193 BOOST_ASIO_CORO_YIELD
201 BOOST_ASIO_CORO_YIELD
202 beast::http::async_write_some(
203 s_, sr_, std::move(*this));
204 bytes_transferred_ += bytes_transferred;
211 this->complete_now(ec, bytes_transferred_);
216 //------------------------------------------------------------------------------
221 bool isRequest, class Body, class Fields>
223 : public beast::stable_async_base<
224 Handler, beast::executor_type<Stream>>
227 serializer<isRequest, Body, Fields>& sr_;
238 Handler, beast::executor_type<Stream>>(
239 std::forward<Handler_>(h), s.get_executor())
241 , sr_(beast::allocate_stable<
242 serializer<isRequest, Body, Fields>>(
243 *this, std::forward<Args>(args)...))
251 async_write(s_, sr_, std::move(*this));
256 error_code ec, std::size_t bytes_transferred)
258 this->complete_now(ec, bytes_transferred);
262 struct run_write_some_op
267 bool isRequest, class Body, class Fields>
272 serializer<isRequest, Body, Fields>* sr)
274 // If you get an error on the following line it means
275 // that your handler does not meet the documented type
276 // requirements for the handler.
279 beast::detail::is_invocable<WriteHandler,
280 void(error_code, std::size_t)>::value,
281 "WriteHandler type requirements not met");
284 typename std::decay<WriteHandler>::type,
286 isRequest, Body, Fields>(
287 std::forward<WriteHandler>(h), *s, *sr);
297 bool isRequest, class Body, class Fields>
303 serializer<isRequest, Body, Fields>* sr)
305 // If you get an error on the following line it means
306 // that your handler does not meet the documented type
307 // requirements for the handler.
310 beast::detail::is_invocable<WriteHandler,
311 void(error_code, std::size_t)>::value,
312 "WriteHandler type requirements not met");
315 typename std::decay<WriteHandler>::type,
318 isRequest, Body, Fields>(
319 std::forward<WriteHandler>(h), *s, *sr);
323 struct run_write_msg_op
328 bool isRequest, class Body, class Fields,
334 message<isRequest, Body, Fields>* m,
338 // If you get an error on the following line it means
339 // that your handler does not meet the documented type
340 // requirements for the handler.
343 beast::detail::is_invocable<WriteHandler,
344 void(error_code, std::size_t)>::value,
345 "WriteHandler type requirements not met");
348 typename std::decay<WriteHandler>::type,
350 isRequest, Body, Fields>(
351 std::forward<WriteHandler>(h), *s, *m,
352 std::forward<Args>(args)...);
358 bool isRequest, class Body, class Fields,
364 message<isRequest, Body, Fields> const* m,
368 // If you get an error on the following line it means
369 // that your handler does not meet the documented type
370 // requirements for the handler.
373 beast::detail::is_invocable<WriteHandler,
374 void(error_code, std::size_t)>::value,
375 "WriteHandler type requirements not met");
378 typename std::decay<WriteHandler>::type,
380 isRequest, Body, Fields>(
381 std::forward<WriteHandler>(h), *s, *m,
382 std::forward<Args>(args)...);
386 //------------------------------------------------------------------------------
388 template<class Stream>
389 class write_some_lambda
394 bool invoked = false;
395 std::size_t bytes_transferred = 0;
398 write_some_lambda(Stream& stream)
403 template<class ConstBufferSequence>
405 operator()(error_code& ec,
406 ConstBufferSequence const& buffers)
410 stream_.write_some(buffers, ec);
414 template<class Stream>
420 bool invoked = false;
421 std::size_t bytes_transferred = 0;
424 write_lambda(Stream& stream)
429 template<class ConstBufferSequence>
431 operator()(error_code& ec,
432 ConstBufferSequence const& buffers)
435 bytes_transferred = net::write(
436 stream_, buffers, ec);
441 class SyncWriteStream,
442 bool isRequest, class Body, class Fields>
445 SyncWriteStream& stream,
446 serializer<isRequest, Body, Fields>& sr,
451 write_some_lambda<SyncWriteStream> f{stream};
454 return f.bytes_transferred;
456 sr.consume(f.bytes_transferred);
457 return f.bytes_transferred;
464 class AsyncWriteStream,
465 bool isRequest, class Body, class Fields,
467 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
468 async_write_some_impl(
469 AsyncWriteStream& stream,
470 serializer<isRequest, Body, Fields>& sr,
471 WriteHandler&& handler)
473 return net::async_initiate<
475 void(error_code, std::size_t)>(
484 //------------------------------------------------------------------------------
487 class SyncWriteStream,
488 bool isRequest, class Body, class Fields>
491 SyncWriteStream& stream,
492 serializer<isRequest, Body, Fields>& sr)
494 static_assert(is_sync_write_stream<SyncWriteStream>::value,
495 "SyncWriteStream type requirements not met");
496 static_assert(is_body<Body>::value,
497 "Body type requirements not met");
498 static_assert(is_body_writer<Body>::value,
499 "BodyWriter type requirements not met");
501 auto const bytes_transferred =
502 write_some(stream, sr, ec);
504 BOOST_THROW_EXCEPTION(system_error{ec});
505 return bytes_transferred;
509 class SyncWriteStream,
510 bool isRequest, class Body, class Fields>
513 SyncWriteStream& stream,
514 serializer<isRequest, Body, Fields>& sr,
517 static_assert(is_sync_write_stream<SyncWriteStream>::value,
518 "SyncWriteStream type requirements not met");
519 static_assert(is_body<Body>::value,
520 "Body type requirements not met");
521 static_assert(is_body_writer<Body>::value,
522 "BodyWriter type requirements not met");
523 return detail::write_some_impl(stream, sr, ec);
527 class AsyncWriteStream,
528 bool isRequest, class Body, class Fields,
530 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
532 AsyncWriteStream& stream,
533 serializer<isRequest, Body, Fields>& sr,
534 WriteHandler&& handler)
536 static_assert(is_async_write_stream<
537 AsyncWriteStream>::value,
538 "AsyncWriteStream type requirements not met");
539 static_assert(is_body<Body>::value,
540 "Body type requirements not met");
541 static_assert(is_body_writer<Body>::value,
542 "BodyWriter type requirements not met");
543 return detail::async_write_some_impl(stream, sr,
544 std::forward<WriteHandler>(handler));
547 //------------------------------------------------------------------------------
550 class SyncWriteStream,
551 bool isRequest, class Body, class Fields>
553 write_header(SyncWriteStream& stream,
554 serializer<isRequest, Body, Fields>& sr)
556 static_assert(is_sync_write_stream<SyncWriteStream>::value,
557 "SyncWriteStream type requirements not met");
558 static_assert(is_body<Body>::value,
559 "Body type requirements not met");
560 static_assert(is_body_writer<Body>::value,
561 "BodyWriter type requirements not met");
563 auto const bytes_transferred =
564 write_header(stream, sr, ec);
566 BOOST_THROW_EXCEPTION(system_error{ec});
567 return bytes_transferred;
571 class SyncWriteStream,
572 bool isRequest, class Body, class Fields>
575 SyncWriteStream& stream,
576 serializer<isRequest, Body, Fields>& sr,
579 static_assert(is_sync_write_stream<SyncWriteStream>::value,
580 "SyncWriteStream type requirements not met");
581 static_assert(is_body<Body>::value,
582 "Body type requirements not met");
583 static_assert(is_body_writer<Body>::value,
584 "BodyWriter type requirements not met");
586 std::size_t bytes_transferred = 0;
587 if(! sr.is_header_done())
589 detail::write_lambda<SyncWriteStream> f{stream};
593 bytes_transferred += f.bytes_transferred;
595 return bytes_transferred;
596 BOOST_ASSERT(f.invoked);
597 sr.consume(f.bytes_transferred);
599 while(! sr.is_header_done());
605 return bytes_transferred;
609 class AsyncWriteStream,
610 bool isRequest, class Body, class Fields,
612 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
614 AsyncWriteStream& stream,
615 serializer<isRequest, Body, Fields>& sr,
616 WriteHandler&& handler)
618 static_assert(is_async_write_stream<
619 AsyncWriteStream>::value,
620 "AsyncWriteStream type requirements not met");
621 static_assert(is_body<Body>::value,
622 "Body type requirements not met");
623 static_assert(is_body_writer<Body>::value,
624 "BodyWriter type requirements not met");
626 return net::async_initiate<
628 void(error_code, std::size_t)>(
629 detail::run_write_op{},
632 detail::serializer_is_header_done{},
636 //------------------------------------------------------------------------------
639 class SyncWriteStream,
640 bool isRequest, class Body, class Fields>
643 SyncWriteStream& stream,
644 serializer<isRequest, Body, Fields>& sr)
646 static_assert(is_sync_write_stream<SyncWriteStream>::value,
647 "SyncWriteStream type requirements not met");
649 auto const bytes_transferred =
650 write(stream, sr, ec);
652 BOOST_THROW_EXCEPTION(system_error{ec});
653 return bytes_transferred;
657 class SyncWriteStream,
658 bool isRequest, class Body, class Fields>
661 SyncWriteStream& stream,
662 serializer<isRequest, Body, Fields>& sr,
665 static_assert(is_sync_write_stream<SyncWriteStream>::value,
666 "SyncWriteStream type requirements not met");
667 std::size_t bytes_transferred = 0;
672 write_some(stream, sr, ec);
674 return bytes_transferred;
678 return bytes_transferred;
682 class AsyncWriteStream,
683 bool isRequest, class Body, class Fields,
685 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
687 AsyncWriteStream& stream,
688 serializer<isRequest, Body, Fields>& sr,
689 WriteHandler&& handler)
691 static_assert(is_async_write_stream<
692 AsyncWriteStream>::value,
693 "AsyncWriteStream type requirements not met");
694 static_assert(is_body<Body>::value,
695 "Body type requirements not met");
696 static_assert(is_body_writer<Body>::value,
697 "BodyWriter type requirements not met");
699 return net::async_initiate<
701 void(error_code, std::size_t)>(
702 detail::run_write_op{},
705 detail::serializer_is_done{},
709 //------------------------------------------------------------------------------
712 class SyncWriteStream,
713 bool isRequest, class Body, class Fields>
714 typename std::enable_if<
715 is_mutable_body_writer<Body>::value,
718 SyncWriteStream& stream,
719 message<isRequest, Body, Fields>& msg)
721 static_assert(is_sync_write_stream<SyncWriteStream>::value,
722 "SyncWriteStream type requirements not met");
723 static_assert(is_body<Body>::value,
724 "Body type requirements not met");
725 static_assert(is_body_writer<Body>::value,
726 "BodyWriter type requirements not met");
728 auto const bytes_transferred =
729 write(stream, msg, ec);
731 BOOST_THROW_EXCEPTION(system_error{ec});
732 return bytes_transferred;
736 class SyncWriteStream,
737 bool isRequest, class Body, class Fields>
738 typename std::enable_if<
739 ! is_mutable_body_writer<Body>::value,
742 SyncWriteStream& stream,
743 message<isRequest, Body, Fields> const& msg)
745 static_assert(is_sync_write_stream<SyncWriteStream>::value,
746 "SyncWriteStream type requirements not met");
747 static_assert(is_body<Body>::value,
748 "Body type requirements not met");
749 static_assert(is_body_writer<Body>::value,
750 "BodyWriter type requirements not met");
752 auto const bytes_transferred =
753 write(stream, msg, ec);
755 BOOST_THROW_EXCEPTION(system_error{ec});
756 return bytes_transferred;
760 class SyncWriteStream,
761 bool isRequest, class Body, class Fields>
762 typename std::enable_if<
763 is_mutable_body_writer<Body>::value,
766 SyncWriteStream& stream,
767 message<isRequest, Body, Fields>& msg,
770 static_assert(is_sync_write_stream<SyncWriteStream>::value,
771 "SyncWriteStream type requirements not met");
772 static_assert(is_body<Body>::value,
773 "Body type requirements not met");
774 static_assert(is_body_writer<Body>::value,
775 "BodyWriter type requirements not met");
776 serializer<isRequest, Body, Fields> sr{msg};
777 return write(stream, sr, ec);
781 class SyncWriteStream,
782 bool isRequest, class Body, class Fields>
783 typename std::enable_if<
784 ! is_mutable_body_writer<Body>::value,
787 SyncWriteStream& stream,
788 message<isRequest, Body, Fields> const& msg,
791 static_assert(is_sync_write_stream<SyncWriteStream>::value,
792 "SyncWriteStream type requirements not met");
793 static_assert(is_body<Body>::value,
794 "Body type requirements not met");
795 static_assert(is_body_writer<Body>::value,
796 "BodyWriter type requirements not met");
797 serializer<isRequest, Body, Fields> sr{msg};
798 return write(stream, sr, ec);
802 class AsyncWriteStream,
803 bool isRequest, class Body, class Fields,
805 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
807 AsyncWriteStream& stream,
808 message<isRequest, Body, Fields>& msg,
809 WriteHandler&& handler,
810 typename std::enable_if<
811 is_mutable_body_writer<Body>::value>::type*)
814 is_async_write_stream<AsyncWriteStream>::value,
815 "AsyncWriteStream type requirements not met");
816 static_assert(is_body<Body>::value,
817 "Body type requirements not met");
818 static_assert(is_body_writer<Body>::value,
819 "BodyWriter type requirements not met");
820 return net::async_initiate<
822 void(error_code, std::size_t)>(
823 detail::run_write_msg_op{},
831 class AsyncWriteStream,
832 bool isRequest, class Body, class Fields,
834 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
836 AsyncWriteStream& stream,
837 message<isRequest, Body, Fields> const& msg,
838 WriteHandler&& handler,
839 typename std::enable_if<
840 ! is_mutable_body_writer<Body>::value>::type*)
843 is_async_write_stream<AsyncWriteStream>::value,
844 "AsyncWriteStream type requirements not met");
845 static_assert(is_body<Body>::value,
846 "Body type requirements not met");
847 static_assert(is_body_writer<Body>::value,
848 "BodyWriter type requirements not met");
849 return net::async_initiate<
851 void(error_code, std::size_t)>(
852 detail::run_write_msg_op{},
859 //------------------------------------------------------------------------------
863 template<class Serializer>
864 class write_ostream_lambda
870 write_ostream_lambda(std::ostream& os,
877 template<class ConstBufferSequence>
879 operator()(error_code& ec,
880 ConstBufferSequence const& buffers) const
885 std::size_t bytes_transferred = 0;
886 for(auto b : beast::buffers_range_ref(buffers))
888 os_.write(static_cast<char const*>(
889 b.data()), b.size());
892 bytes_transferred += b.size();
894 sr_.consume(bytes_transferred);
900 template<class Fields>
902 operator<<(std::ostream& os,
903 header<true, Fields> const& h)
905 typename Fields::writer fr{
906 h, h.version(), h.method()};
907 return os << beast::make_printable(fr.get());
910 template<class Fields>
912 operator<<(std::ostream& os,
913 header<false, Fields> const& h)
915 typename Fields::writer fr{
916 h, h.version(), h.result_int()};
917 return os << beast::make_printable(fr.get());
920 template<bool isRequest, class Body, class Fields>
922 operator<<(std::ostream& os,
923 message<isRequest, Body, Fields> const& msg)
925 static_assert(is_body<Body>::value,
926 "Body type requirements not met");
927 static_assert(is_body_writer<Body>::value,
928 "BodyWriter type requirements not met");
929 serializer<isRequest, Body, Fields> sr{msg};
931 detail::write_ostream_lambda<decltype(sr)> f{os, sr};
939 os.setstate(std::ios::failbit);
943 while(! sr.is_done());