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)
63 BOOST_ASIO_HANDLER_LOCATION((
65 "http::async_write_some"));
69 op_.s_.async_write_some(
70 buffers, std::move(op_));
75 template<class Handler_>
79 serializer<isRequest, Body, Fields>& sr)
81 Handler, beast::executor_type<Stream>>(
82 std::forward<Handler_>(h), s.get_executor())
99 BOOST_ASSERT(! f.invoked);
101 BOOST_ASIO_HANDLER_LOCATION((
103 "http::async_write_some"));
107 beast::bind_front_handler(
108 std::move(*this), ec, 0));
112 // *this is now moved-from,
115 // What else could it be?
116 BOOST_ASSERT(sr_.is_done());
119 BOOST_ASIO_HANDLER_LOCATION((
121 "http::async_write_some"));
125 beast::bind_front_handler(
126 std::move(*this), ec, 0));
132 std::size_t bytes_transferred)
135 sr_.consume(bytes_transferred);
136 this->complete_now(ec, bytes_transferred);
140 //------------------------------------------------------------------------------
142 struct serializer_is_header_done
145 bool isRequest, class Body, class Fields>
148 serializer<isRequest, Body, Fields>& sr) const
150 return sr.is_header_done();
154 struct serializer_is_done
157 bool isRequest, class Body, class Fields>
160 serializer<isRequest, Body, Fields>& sr) const
166 //------------------------------------------------------------------------------
172 bool isRequest, class Body, class Fields>
174 : public beast::async_base<
175 Handler, beast::executor_type<Stream>>
176 , public asio::coroutine
179 serializer<isRequest, Body, Fields>& sr_;
180 std::size_t bytes_transferred_ = 0;
183 template<class Handler_>
187 serializer<isRequest, Body, Fields>& sr)
189 Handler, beast::executor_type<Stream>>(
190 std::forward<Handler_>(h), s.get_executor())
200 std::size_t bytes_transferred = 0)
202 BOOST_ASIO_CORO_REENTER(*this)
206 BOOST_ASIO_CORO_YIELD
208 BOOST_ASIO_HANDLER_LOCATION((
210 "http::async_write"));
220 BOOST_ASIO_CORO_YIELD
222 BOOST_ASIO_HANDLER_LOCATION((
224 "http::async_write"));
226 beast::http::async_write_some(
227 s_, sr_, std::move(*this));
229 bytes_transferred_ += bytes_transferred;
236 this->complete_now(ec, bytes_transferred_);
241 //------------------------------------------------------------------------------
246 bool isRequest, class Body, class Fields>
248 : public beast::stable_async_base<
249 Handler, beast::executor_type<Stream>>
252 serializer<isRequest, Body, Fields>& sr_;
263 Handler, beast::executor_type<Stream>>(
264 std::forward<Handler_>(h), s.get_executor())
266 , sr_(beast::allocate_stable<
267 serializer<isRequest, Body, Fields>>(
268 *this, std::forward<Args>(args)...))
276 BOOST_ASIO_HANDLER_LOCATION((
278 "http::async_write(msg)"));
280 async_write(s_, sr_, std::move(*this));
285 error_code ec, std::size_t bytes_transferred)
287 this->complete_now(ec, bytes_transferred);
291 struct run_write_some_op
296 bool isRequest, class Body, class Fields>
301 serializer<isRequest, Body, Fields>* sr)
303 // If you get an error on the following line it means
304 // that your handler does not meet the documented type
305 // requirements for the handler.
308 beast::detail::is_invocable<WriteHandler,
309 void(error_code, std::size_t)>::value,
310 "WriteHandler type requirements not met");
313 typename std::decay<WriteHandler>::type,
315 isRequest, Body, Fields>(
316 std::forward<WriteHandler>(h), *s, *sr);
326 bool isRequest, class Body, class Fields>
332 serializer<isRequest, Body, Fields>* sr)
334 // If you get an error on the following line it means
335 // that your handler does not meet the documented type
336 // requirements for the handler.
339 beast::detail::is_invocable<WriteHandler,
340 void(error_code, std::size_t)>::value,
341 "WriteHandler type requirements not met");
344 typename std::decay<WriteHandler>::type,
347 isRequest, Body, Fields>(
348 std::forward<WriteHandler>(h), *s, *sr);
352 struct run_write_msg_op
357 bool isRequest, class Body, class Fields,
363 message<isRequest, Body, Fields>* m,
367 // If you get an error on the following line it means
368 // that your handler does not meet the documented type
369 // requirements for the handler.
372 beast::detail::is_invocable<WriteHandler,
373 void(error_code, std::size_t)>::value,
374 "WriteHandler type requirements not met");
377 typename std::decay<WriteHandler>::type,
379 isRequest, Body, Fields>(
380 std::forward<WriteHandler>(h), *s, *m,
381 std::forward<Args>(args)...);
387 bool isRequest, class Body, class Fields,
393 message<isRequest, Body, Fields> const* m,
397 // If you get an error on the following line it means
398 // that your handler does not meet the documented type
399 // requirements for the handler.
402 beast::detail::is_invocable<WriteHandler,
403 void(error_code, std::size_t)>::value,
404 "WriteHandler type requirements not met");
407 typename std::decay<WriteHandler>::type,
409 isRequest, Body, Fields>(
410 std::forward<WriteHandler>(h), *s, *m,
411 std::forward<Args>(args)...);
415 //------------------------------------------------------------------------------
417 template<class Stream>
418 class write_some_lambda
423 bool invoked = false;
424 std::size_t bytes_transferred = 0;
427 write_some_lambda(Stream& stream)
432 template<class ConstBufferSequence>
434 operator()(error_code& ec,
435 ConstBufferSequence const& buffers)
439 stream_.write_some(buffers, ec);
443 template<class Stream>
449 bool invoked = false;
450 std::size_t bytes_transferred = 0;
453 write_lambda(Stream& stream)
458 template<class ConstBufferSequence>
460 operator()(error_code& ec,
461 ConstBufferSequence const& buffers)
464 bytes_transferred = net::write(
465 stream_, buffers, ec);
470 class SyncWriteStream,
471 bool isRequest, class Body, class Fields>
474 SyncWriteStream& stream,
475 serializer<isRequest, Body, Fields>& sr,
480 write_some_lambda<SyncWriteStream> f{stream};
483 return f.bytes_transferred;
485 sr.consume(f.bytes_transferred);
486 return f.bytes_transferred;
493 class AsyncWriteStream,
494 bool isRequest, class Body, class Fields,
495 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
496 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
497 async_write_some_impl(
498 AsyncWriteStream& stream,
499 serializer<isRequest, Body, Fields>& sr,
500 WriteHandler&& handler)
502 return net::async_initiate<
504 void(error_code, std::size_t)>(
513 //------------------------------------------------------------------------------
516 class SyncWriteStream,
517 bool isRequest, class Body, class Fields>
520 SyncWriteStream& stream,
521 serializer<isRequest, Body, Fields>& sr)
523 static_assert(is_sync_write_stream<SyncWriteStream>::value,
524 "SyncWriteStream type requirements not met");
525 static_assert(is_body<Body>::value,
526 "Body type requirements not met");
527 static_assert(is_body_writer<Body>::value,
528 "BodyWriter type requirements not met");
530 auto const bytes_transferred =
531 write_some(stream, sr, ec);
533 BOOST_THROW_EXCEPTION(system_error{ec});
534 return bytes_transferred;
538 class SyncWriteStream,
539 bool isRequest, class Body, class Fields>
542 SyncWriteStream& stream,
543 serializer<isRequest, Body, Fields>& sr,
546 static_assert(is_sync_write_stream<SyncWriteStream>::value,
547 "SyncWriteStream type requirements not met");
548 static_assert(is_body<Body>::value,
549 "Body type requirements not met");
550 static_assert(is_body_writer<Body>::value,
551 "BodyWriter type requirements not met");
552 return detail::write_some_impl(stream, sr, ec);
556 class AsyncWriteStream,
557 bool isRequest, class Body, class Fields,
558 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
559 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
561 AsyncWriteStream& stream,
562 serializer<isRequest, Body, Fields>& sr,
563 WriteHandler&& handler)
565 static_assert(is_async_write_stream<
566 AsyncWriteStream>::value,
567 "AsyncWriteStream type requirements not met");
568 static_assert(is_body<Body>::value,
569 "Body type requirements not met");
570 static_assert(is_body_writer<Body>::value,
571 "BodyWriter type requirements not met");
572 return detail::async_write_some_impl(stream, sr,
573 std::forward<WriteHandler>(handler));
576 //------------------------------------------------------------------------------
579 class SyncWriteStream,
580 bool isRequest, class Body, class Fields>
582 write_header(SyncWriteStream& stream,
583 serializer<isRequest, Body, Fields>& sr)
585 static_assert(is_sync_write_stream<SyncWriteStream>::value,
586 "SyncWriteStream type requirements not met");
587 static_assert(is_body<Body>::value,
588 "Body type requirements not met");
589 static_assert(is_body_writer<Body>::value,
590 "BodyWriter type requirements not met");
592 auto const bytes_transferred =
593 write_header(stream, sr, ec);
595 BOOST_THROW_EXCEPTION(system_error{ec});
596 return bytes_transferred;
600 class SyncWriteStream,
601 bool isRequest, class Body, class Fields>
604 SyncWriteStream& stream,
605 serializer<isRequest, Body, Fields>& sr,
608 static_assert(is_sync_write_stream<SyncWriteStream>::value,
609 "SyncWriteStream type requirements not met");
610 static_assert(is_body<Body>::value,
611 "Body type requirements not met");
612 static_assert(is_body_writer<Body>::value,
613 "BodyWriter type requirements not met");
615 std::size_t bytes_transferred = 0;
616 if(! sr.is_header_done())
618 detail::write_lambda<SyncWriteStream> f{stream};
622 bytes_transferred += f.bytes_transferred;
624 return bytes_transferred;
625 BOOST_ASSERT(f.invoked);
626 sr.consume(f.bytes_transferred);
628 while(! sr.is_header_done());
634 return bytes_transferred;
638 class AsyncWriteStream,
639 bool isRequest, class Body, class Fields,
640 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
641 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
643 AsyncWriteStream& stream,
644 serializer<isRequest, Body, Fields>& sr,
645 WriteHandler&& handler)
647 static_assert(is_async_write_stream<
648 AsyncWriteStream>::value,
649 "AsyncWriteStream type requirements not met");
650 static_assert(is_body<Body>::value,
651 "Body type requirements not met");
652 static_assert(is_body_writer<Body>::value,
653 "BodyWriter type requirements not met");
655 return net::async_initiate<
657 void(error_code, std::size_t)>(
658 detail::run_write_op{},
661 detail::serializer_is_header_done{},
665 //------------------------------------------------------------------------------
668 class SyncWriteStream,
669 bool isRequest, class Body, class Fields>
672 SyncWriteStream& stream,
673 serializer<isRequest, Body, Fields>& sr)
675 static_assert(is_sync_write_stream<SyncWriteStream>::value,
676 "SyncWriteStream type requirements not met");
678 auto const bytes_transferred =
679 write(stream, sr, ec);
681 BOOST_THROW_EXCEPTION(system_error{ec});
682 return bytes_transferred;
686 class SyncWriteStream,
687 bool isRequest, class Body, class Fields>
690 SyncWriteStream& stream,
691 serializer<isRequest, Body, Fields>& sr,
694 static_assert(is_sync_write_stream<SyncWriteStream>::value,
695 "SyncWriteStream type requirements not met");
696 std::size_t bytes_transferred = 0;
701 write_some(stream, sr, ec);
703 return bytes_transferred;
707 return bytes_transferred;
711 class AsyncWriteStream,
712 bool isRequest, class Body, class Fields,
713 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
714 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
716 AsyncWriteStream& stream,
717 serializer<isRequest, Body, Fields>& sr,
718 WriteHandler&& handler)
720 static_assert(is_async_write_stream<
721 AsyncWriteStream>::value,
722 "AsyncWriteStream 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 return net::async_initiate<
730 void(error_code, std::size_t)>(
731 detail::run_write_op{},
734 detail::serializer_is_done{},
738 //------------------------------------------------------------------------------
741 class SyncWriteStream,
742 bool isRequest, class Body, class Fields>
743 typename std::enable_if<
744 is_mutable_body_writer<Body>::value,
747 SyncWriteStream& stream,
748 message<isRequest, Body, Fields>& msg)
750 static_assert(is_sync_write_stream<SyncWriteStream>::value,
751 "SyncWriteStream type requirements not met");
752 static_assert(is_body<Body>::value,
753 "Body type requirements not met");
754 static_assert(is_body_writer<Body>::value,
755 "BodyWriter type requirements not met");
757 auto const bytes_transferred =
758 write(stream, msg, ec);
760 BOOST_THROW_EXCEPTION(system_error{ec});
761 return bytes_transferred;
765 class SyncWriteStream,
766 bool isRequest, class Body, class Fields>
767 typename std::enable_if<
768 ! is_mutable_body_writer<Body>::value,
771 SyncWriteStream& stream,
772 message<isRequest, Body, Fields> const& msg)
774 static_assert(is_sync_write_stream<SyncWriteStream>::value,
775 "SyncWriteStream type requirements not met");
776 static_assert(is_body<Body>::value,
777 "Body type requirements not met");
778 static_assert(is_body_writer<Body>::value,
779 "BodyWriter type requirements not met");
781 auto const bytes_transferred =
782 write(stream, msg, ec);
784 BOOST_THROW_EXCEPTION(system_error{ec});
785 return bytes_transferred;
789 class SyncWriteStream,
790 bool isRequest, class Body, class Fields>
791 typename std::enable_if<
792 is_mutable_body_writer<Body>::value,
795 SyncWriteStream& stream,
796 message<isRequest, Body, Fields>& msg,
799 static_assert(is_sync_write_stream<SyncWriteStream>::value,
800 "SyncWriteStream type requirements not met");
801 static_assert(is_body<Body>::value,
802 "Body type requirements not met");
803 static_assert(is_body_writer<Body>::value,
804 "BodyWriter type requirements not met");
805 serializer<isRequest, Body, Fields> sr{msg};
806 return write(stream, sr, ec);
810 class SyncWriteStream,
811 bool isRequest, class Body, class Fields>
812 typename std::enable_if<
813 ! is_mutable_body_writer<Body>::value,
816 SyncWriteStream& stream,
817 message<isRequest, Body, Fields> const& msg,
820 static_assert(is_sync_write_stream<SyncWriteStream>::value,
821 "SyncWriteStream type requirements not met");
822 static_assert(is_body<Body>::value,
823 "Body type requirements not met");
824 static_assert(is_body_writer<Body>::value,
825 "BodyWriter type requirements not met");
826 serializer<isRequest, Body, Fields> sr{msg};
827 return write(stream, sr, ec);
831 class AsyncWriteStream,
832 bool isRequest, class Body, class Fields,
833 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
834 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
836 AsyncWriteStream& stream,
837 message<isRequest, Body, Fields>& 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{},
860 class AsyncWriteStream,
861 bool isRequest, class Body, class Fields,
862 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
863 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
865 AsyncWriteStream& stream,
866 message<isRequest, Body, Fields> const& msg,
867 WriteHandler&& handler,
868 typename std::enable_if<
869 ! is_mutable_body_writer<Body>::value>::type*)
872 is_async_write_stream<AsyncWriteStream>::value,
873 "AsyncWriteStream type requirements not met");
874 static_assert(is_body<Body>::value,
875 "Body type requirements not met");
876 static_assert(is_body_writer<Body>::value,
877 "BodyWriter type requirements not met");
878 return net::async_initiate<
880 void(error_code, std::size_t)>(
881 detail::run_write_msg_op{},
888 //------------------------------------------------------------------------------
892 template<class Serializer>
893 class write_ostream_lambda
899 write_ostream_lambda(std::ostream& os,
906 template<class ConstBufferSequence>
908 operator()(error_code& ec,
909 ConstBufferSequence const& buffers) const
914 std::size_t bytes_transferred = 0;
915 for(auto b : beast::buffers_range_ref(buffers))
917 os_.write(static_cast<char const*>(
918 b.data()), b.size());
921 bytes_transferred += b.size();
923 sr_.consume(bytes_transferred);
929 template<class Fields>
931 operator<<(std::ostream& os,
932 header<true, Fields> const& h)
934 typename Fields::writer fr{
935 h, h.version(), h.method()};
936 return os << beast::make_printable(fr.get());
939 template<class Fields>
941 operator<<(std::ostream& os,
942 header<false, Fields> const& h)
944 typename Fields::writer fr{
945 h, h.version(), h.result_int()};
946 return os << beast::make_printable(fr.get());
949 template<bool isRequest, class Body, class Fields>
951 operator<<(std::ostream& os,
952 message<isRequest, Body, Fields> const& msg)
954 static_assert(is_body<Body>::value,
955 "Body type requirements not met");
956 static_assert(is_body_writer<Body>::value,
957 "BodyWriter type requirements not met");
958 serializer<isRequest, Body, Fields> sr{msg};
960 detail::write_ostream_lambda<decltype(sr)> f{os, sr};
968 os.setstate(std::ios::failbit);
972 while(! sr.is_done());