• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
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)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_HTTP_WRITE_HPP
11 #define BOOST_BEAST_HTTP_WRITE_HPP
12 
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/http/message.hpp>
15 #include <boost/beast/http/serializer.hpp>
16 #include <boost/beast/http/type_traits.hpp>
17 #include <boost/beast/http/detail/chunk_encode.hpp>
18 #include <boost/beast/core/error.hpp>
19 #include <boost/beast/core/stream_traits.hpp>
20 #include <boost/asio/async_result.hpp>
21 #include <iosfwd>
22 #include <limits>
23 #include <memory>
24 #include <type_traits>
25 #include <utility>
26 
27 namespace boost {
28 namespace beast {
29 namespace http {
30 
31 /** Write part of a message to a stream using a serializer.
32 
33     This function is used to write part of a message to a stream using
34     a caller-provided HTTP/1 serializer. The call will block until one
35     of the following conditions is true:
36 
37     @li One or more bytes have been transferred.
38 
39     @li The function @ref serializer::is_done returns `true`
40 
41     @li An error occurs on the stream.
42 
43     This operation is implemented in terms of one or more calls
44     to the stream's `write_some` function.
45 
46     The amount of data actually transferred is controlled by the behavior
47     of the underlying stream, subject to the buffer size limit of the
48     serializer obtained or set through a call to @ref serializer::limit.
49     Setting a limit and performing bounded work helps applications set
50     reasonable timeouts. It also allows application-level flow control
51     to function correctly. For example when using a TCP/IP based
52     stream.
53 
54     @param stream The stream to which the data is to be written.
55     The type must support the <em>SyncWriteStream</em> concept.
56 
57     @param sr The serializer to use.
58 
59     @return The number of bytes written to the stream.
60 
61     @throws system_error Thrown on failure.
62 
63     @see serializer
64 */
65 template<
66     class SyncWriteStream,
67     bool isRequest, class Body, class Fields>
68 std::size_t
69 write_some(
70     SyncWriteStream& stream,
71     serializer<isRequest, Body, Fields>& sr);
72 
73 /** Write part of a message to a stream using a serializer.
74 
75     This function is used to write part of a message to a stream using
76     a caller-provided HTTP/1 serializer. The call will block until one
77     of the following conditions is true:
78 
79     @li One or more bytes have been transferred.
80 
81     @li The function @ref serializer::is_done returns `true`
82 
83     @li An error occurs on the stream.
84 
85     This operation is implemented in terms of one or more calls
86     to the stream's `write_some` function.
87 
88     The amount of data actually transferred is controlled by the behavior
89     of the underlying stream, subject to the buffer size limit of the
90     serializer obtained or set through a call to @ref serializer::limit.
91     Setting a limit and performing bounded work helps applications set
92     reasonable timeouts. It also allows application-level flow control
93     to function correctly. For example when using a TCP/IP based
94     stream.
95 
96     @param stream The stream to which the data is to be written.
97     The type must support the <em>SyncWriteStream</em> concept.
98 
99     @param sr The serializer to use.
100 
101     @param ec Set to indicate what error occurred, if any.
102 
103     @return The number of bytes written to the stream.
104 
105     @see async_write_some, serializer
106 */
107 template<
108     class SyncWriteStream,
109     bool isRequest, class Body, class Fields>
110 std::size_t
111 write_some(
112     SyncWriteStream& stream,
113     serializer<isRequest, Body, Fields>& sr,
114     error_code& ec);
115 
116 /** Write part of a message to a stream asynchronously using a serializer.
117 
118     This function is used to write part of a message to a stream
119     asynchronously using a caller-provided HTTP/1 serializer. The function
120     call always returns immediately. The asynchronous operation will continue
121     until one of the following conditions is true:
122 
123     @li One or more bytes have been transferred.
124 
125     @li The function @ref serializer::is_done returns `true`
126 
127     @li An error occurs on the stream.
128 
129     This operation is implemented in terms of zero or more calls to the stream's
130     `async_write_some` function, and is known as a <em>composed operation</em>.
131     The program must ensure that the stream performs no other writes
132     until this operation completes.
133 
134     The amount of data actually transferred is controlled by the behavior
135     of the underlying stream, subject to the buffer size limit of the
136     serializer obtained or set through a call to @ref serializer::limit.
137     Setting a limit and performing bounded work helps applications set
138     reasonable timeouts. It also allows application-level flow control
139     to function correctly. For example when using a TCP/IP based
140     stream.
141 
142     @param stream The stream to which the data is to be written.
143     The type must support the <em>AsyncWriteStream</em> concept.
144 
145     @param sr The serializer to use.
146     The object must remain valid at least until the
147     handler is called; ownership is not transferred.
148 
149     @param handler The completion handler to invoke when the operation
150     completes. The implementation takes ownership of the handler by
151     performing a decay-copy. The equivalent function signature of
152     the handler must be:
153     @code
154     void handler(
155         error_code const& error,        // result of operation
156         std::size_t bytes_transferred   // the number of bytes written to the stream
157     );
158     @endcode
159     Regardless of whether the asynchronous operation completes
160     immediately or not, the handler will not be invoked from within
161     this function. Invocation of the handler will be performed in a
162     manner equivalent to using `net::post`.
163 
164     @see serializer
165 */
166 template<
167     class AsyncWriteStream,
168     bool isRequest, class Body, class Fields,
169     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
170         net::default_completion_token_t<
171             executor_type<AsyncWriteStream>>>
172 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
173 async_write_some(
174     AsyncWriteStream& stream,
175     serializer<isRequest, Body, Fields>& sr,
176     WriteHandler&& handler =
177         net::default_completion_token_t<
178             executor_type<AsyncWriteStream>>{});
179 
180 //------------------------------------------------------------------------------
181 
182 /** Write a header to a stream using a serializer.
183 
184     This function is used to write a header to a stream using a
185     caller-provided HTTP/1 serializer. The call will block until one
186     of the following conditions is true:
187 
188     @li The function @ref serializer::is_header_done returns `true`
189 
190     @li An error occurs.
191 
192     This operation is implemented in terms of one or more calls
193     to the stream's `write_some` function.
194 
195     @param stream The stream to which the data is to be written.
196     The type must support the <em>SyncWriteStream</em> concept.
197 
198     @param sr The serializer to use.
199 
200     @return The number of bytes written to the stream.
201 
202     @throws system_error Thrown on failure.
203 
204     @note The implementation will call @ref serializer::split with
205     the value `true` on the serializer passed in.
206 
207     @see serializer
208 */
209 template<
210     class SyncWriteStream,
211     bool isRequest, class Body, class Fields>
212 std::size_t
213 write_header(
214     SyncWriteStream& stream,
215     serializer<isRequest, Body, Fields>& sr);
216 
217 /** Write a header to a stream using a serializer.
218 
219     This function is used to write a header to a stream using a
220     caller-provided HTTP/1 serializer. The call will block until one
221     of the following conditions is true:
222 
223     @li The function @ref serializer::is_header_done returns `true`
224 
225     @li An error occurs.
226 
227     This operation is implemented in terms of one or more calls
228     to the stream's `write_some` function.
229 
230     @param stream The stream to which the data is to be written.
231     The type must support the <em>SyncWriteStream</em> concept.
232 
233     @param sr The serializer to use.
234 
235     @param ec Set to indicate what error occurred, if any.
236 
237     @return The number of bytes written to the stream.
238 
239     @note The implementation will call @ref serializer::split with
240     the value `true` on the serializer passed in.
241 
242     @see serializer
243 */
244 template<
245     class SyncWriteStream,
246     bool isRequest, class Body, class Fields>
247 std::size_t
248 write_header(
249     SyncWriteStream& stream,
250     serializer<isRequest, Body, Fields>& sr,
251     error_code& ec);
252 
253 /** Write a header to a stream asynchronously using a serializer.
254 
255     This function is used to write a header to a stream asynchronously
256     using a caller-provided HTTP/1 serializer. The function call always
257     returns immediately. The asynchronous operation will continue until
258     one of the following conditions is true:
259 
260     @li The function @ref serializer::is_header_done returns `true`
261 
262     @li An error occurs.
263 
264     This operation is implemented in terms of zero or more calls to the stream's
265     `async_write_some` function, and is known as a <em>composed operation</em>.
266     The program must ensure that the stream performs no other writes
267     until this operation completes.
268 
269     @param stream The stream to which the data is to be written.
270     The type must support the <em>AsyncWriteStream</em> concept.
271 
272     @param sr The serializer to use.
273     The object must remain valid at least until the
274     handler is called; ownership is not transferred.
275 
276     @param handler The completion handler to invoke when the operation
277     completes. The implementation takes ownership of the handler by
278     performing a decay-copy. The equivalent function signature of
279     the handler must be:
280     @code
281     void handler(
282         error_code const& error,        // result of operation
283         std::size_t bytes_transferred   // the number of bytes written to the stream
284     );
285     @endcode
286     Regardless of whether the asynchronous operation completes
287     immediately or not, the handler will not be invoked from within
288     this function. Invocation of the handler will be performed in a
289     manner equivalent to using `net::post`.
290 
291     @note The implementation will call @ref serializer::split with
292     the value `true` on the serializer passed in.
293 
294     @see serializer
295 */
296 template<
297     class AsyncWriteStream,
298     bool isRequest, class Body, class Fields,
299     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
300         net::default_completion_token_t<
301             executor_type<AsyncWriteStream>>>
302 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
303 async_write_header(
304     AsyncWriteStream& stream,
305     serializer<isRequest, Body, Fields>& sr,
306     WriteHandler&& handler =
307         net::default_completion_token_t<
308             executor_type<AsyncWriteStream>>{});
309 
310 //------------------------------------------------------------------------------
311 
312 /** Write a complete message to a stream using a serializer.
313 
314     This function is used to write a complete message to a stream using
315     a caller-provided HTTP/1 serializer. The call will block until one
316     of the following conditions is true:
317 
318     @li The function @ref serializer::is_done returns `true`
319 
320     @li An error occurs.
321 
322     This operation is implemented in terms of one or more calls
323     to the stream's `write_some` function.
324 
325     @param stream The stream to which the data is to be written.
326     The type must support the <em>SyncWriteStream</em> concept.
327 
328     @param sr The serializer to use.
329 
330     @return The number of bytes written to the stream.
331 
332     @throws system_error Thrown on failure.
333 
334     @see serializer
335 */
336 template<
337     class SyncWriteStream,
338     bool isRequest, class Body, class Fields>
339 std::size_t
340 write(
341     SyncWriteStream& stream,
342     serializer<isRequest, Body, Fields>& sr);
343 
344 /** Write a complete message to a stream using a serializer.
345 
346     This function is used to write a complete message to a stream using
347     a caller-provided HTTP/1 serializer. The call will block until one
348     of the following conditions is true:
349 
350     @li The function @ref serializer::is_done returns `true`
351 
352     @li An error occurs.
353 
354     This operation is implemented in terms of one or more calls
355     to the stream's `write_some` function.
356 
357     @param stream The stream to which the data is to be written.
358     The type must support the <em>SyncWriteStream</em> concept.
359 
360     @param sr The serializer to use.
361 
362     @param ec Set to the error, if any occurred.
363 
364     @return The number of bytes written to the stream.
365 
366     @see serializer
367 */
368 template<
369     class SyncWriteStream,
370     bool isRequest, class Body, class Fields>
371 std::size_t
372 write(
373     SyncWriteStream& stream,
374     serializer<isRequest, Body, Fields>& sr,
375    error_code& ec);
376 
377 /** Write a complete message to a stream asynchronously using a serializer.
378 
379     This function is used to write a complete message to a stream
380     asynchronously using a caller-provided HTTP/1 serializer. The
381     function call always returns immediately. The asynchronous
382     operation will continue until one of the following conditions is true:
383 
384     @li The function @ref serializer::is_done returns `true`
385 
386     @li An error occurs.
387 
388     This operation is implemented in terms of zero or more calls to the stream's
389     `async_write_some` function, and is known as a <em>composed operation</em>.
390     The program must ensure that the stream performs no other writes
391     until this operation completes.
392 
393     @param stream The stream to which the data is to be written.
394     The type must support the <em>AsyncWriteStream</em> concept.
395 
396     @param sr The serializer to use.
397     The object must remain valid at least until the
398     handler is called; ownership is not transferred.
399 
400     @param handler The completion handler to invoke when the operation
401     completes. The implementation takes ownership of the handler by
402     performing a decay-copy. The equivalent function signature of
403     the handler must be:
404     @code
405     void handler(
406         error_code const& error,        // result of operation
407         std::size_t bytes_transferred   // the number of bytes written to the stream
408     );
409     @endcode
410     Regardless of whether the asynchronous operation completes
411     immediately or not, the handler will not be invoked from within
412     this function. Invocation of the handler will be performed in a
413     manner equivalent to using `net::post`.
414 
415     @see serializer
416 */
417 template<
418     class AsyncWriteStream,
419     bool isRequest, class Body, class Fields,
420     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
421         net::default_completion_token_t<
422             executor_type<AsyncWriteStream>>>
423 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
424 async_write(
425     AsyncWriteStream& stream,
426     serializer<isRequest, Body, Fields>& sr,
427     WriteHandler&& handler =
428         net::default_completion_token_t<
429             executor_type<AsyncWriteStream>>{});
430 
431 //------------------------------------------------------------------------------
432 
433 /** Write a complete message to a stream.
434 
435     This function is used to write a complete message to a stream using
436     HTTP/1. The call will block until one of the following conditions is true:
437 
438     @li The entire message is written.
439 
440     @li An error occurs.
441 
442     This operation is implemented in terms of one or more calls to the stream's
443     `write_some` function. The algorithm will use a temporary @ref serializer
444     with an empty chunk decorator to produce buffers.
445 
446     @note This function only participates in overload resolution
447     if @ref is_mutable_body_writer for <em>Body</em> returns `true`.
448 
449     @param stream The stream to which the data is to be written.
450     The type must support the <em>SyncWriteStream</em> concept.
451 
452     @param msg The message to write.
453 
454     @return The number of bytes written to the stream.
455 
456     @throws system_error Thrown on failure.
457 
458     @see message
459 */
460 template<
461     class SyncWriteStream,
462     bool isRequest, class Body, class Fields>
463 #if BOOST_BEAST_DOXYGEN
464 std::size_t
465 #else
466 typename std::enable_if<
467     is_mutable_body_writer<Body>::value,
468     std::size_t>::type
469 #endif
470 write(
471     SyncWriteStream& stream,
472     message<isRequest, Body, Fields>& msg);
473 
474 /** Write a complete message to a stream.
475 
476     This function is used to write a complete message to a stream using
477     HTTP/1. The call will block until one of the following conditions is true:
478 
479     @li The entire message is written.
480 
481     @li An error occurs.
482 
483     This operation is implemented in terms of one or more calls to the stream's
484     `write_some` function. The algorithm will use a temporary @ref serializer
485     with an empty chunk decorator to produce buffers.
486 
487     @note This function only participates in overload resolution
488     if @ref is_mutable_body_writer for <em>Body</em> returns `false`.
489 
490     @param stream The stream to which the data is to be written.
491     The type must support the <em>SyncWriteStream</em> concept.
492 
493     @param msg The message to write.
494 
495     @return The number of bytes written to the stream.
496 
497     @throws system_error Thrown on failure.
498 
499     @see message
500 */
501 template<
502     class SyncWriteStream,
503     bool isRequest, class Body, class Fields>
504 #if BOOST_BEAST_DOXYGEN
505 std::size_t
506 #else
507 typename std::enable_if<
508     ! is_mutable_body_writer<Body>::value,
509     std::size_t>::type
510 #endif
511 write(
512     SyncWriteStream& stream,
513     message<isRequest, Body, Fields> const& msg);
514 
515 /** Write a complete message to a stream.
516 
517     This function is used to write a complete message to a stream using
518     HTTP/1. The call will block until one of the following conditions is true:
519 
520     @li The entire message is written.
521 
522     @li An error occurs.
523 
524     This operation is implemented in terms of one or more calls to the stream's
525     `write_some` function. The algorithm will use a temporary @ref serializer
526     with an empty chunk decorator to produce buffers.
527 
528     @note This function only participates in overload resolution
529     if @ref is_mutable_body_writer for <em>Body</em> returns `true`.
530 
531     @param stream The stream to which the data is to be written.
532     The type must support the <em>SyncWriteStream</em> concept.
533 
534     @param msg The message to write.
535 
536     @param ec Set to the error, if any occurred.
537 
538     @return The number of bytes written to the stream.
539 
540     @see message
541 */
542 template<
543     class SyncWriteStream,
544     bool isRequest, class Body, class Fields>
545 #if BOOST_BEAST_DOXYGEN
546 std::size_t
547 #else
548 typename std::enable_if<
549     is_mutable_body_writer<Body>::value,
550     std::size_t>::type
551 #endif
552 write(
553     SyncWriteStream& stream,
554     message<isRequest, Body, Fields>& msg,
555     error_code& ec);
556 
557 /** Write a complete message to a stream.
558 
559     This function is used to write a complete message to a stream using
560     HTTP/1. The call will block until one of the following conditions is true:
561 
562     @li The entire message is written.
563 
564     @li An error occurs.
565 
566     This operation is implemented in terms of one or more calls to the stream's
567     `write_some` function. The algorithm will use a temporary @ref serializer
568     with an empty chunk decorator to produce buffers.
569 
570     @note This function only participates in overload resolution
571     if @ref is_mutable_body_writer for <em>Body</em> returns `false`.
572 
573     @param stream The stream to which the data is to be written.
574     The type must support the <em>SyncWriteStream</em> concept.
575 
576     @param msg The message to write.
577 
578     @param ec Set to the error, if any occurred.
579 
580     @return The number of bytes written to the stream.
581 
582     @see message
583 */
584 template<
585     class SyncWriteStream,
586     bool isRequest, class Body, class Fields>
587 #if BOOST_BEAST_DOXYGEN
588 std::size_t
589 #else
590 typename std::enable_if<
591     ! is_mutable_body_writer<Body>::value,
592     std::size_t>::type
593 #endif
594 write(
595     SyncWriteStream& stream,
596     message<isRequest, Body, Fields> const& msg,
597     error_code& ec);
598 
599 /** Write a complete message to a stream asynchronously.
600 
601     This function is used to write a complete message to a stream asynchronously
602     using HTTP/1. The function call always returns immediately. The asynchronous
603     operation will continue until one of the following conditions is true:
604 
605     @li The entire message is written.
606 
607     @li An error occurs.
608 
609     This operation is implemented in terms of zero or more calls to the stream's
610     `async_write_some` function, and is known as a <em>composed operation</em>.
611     The program must ensure that the stream performs no other writes
612     until this operation completes. The algorithm will use a temporary
613     @ref serializer with an empty chunk decorator to produce buffers.
614 
615     @note This function only participates in overload resolution
616     if @ref is_mutable_body_writer for <em>Body</em> returns `true`.
617 
618     @param stream The stream to which the data is to be written.
619     The type must support the <em>AsyncWriteStream</em> concept.
620 
621     @param msg The message to write.
622     The object must remain valid at least until the
623     handler is called; ownership is not transferred.
624 
625     @param handler The completion handler to invoke when the operation
626     completes. The implementation takes ownership of the handler by
627     performing a decay-copy. The equivalent function signature of
628     the handler must be:
629     @code
630     void handler(
631         error_code const& error,        // result of operation
632         std::size_t bytes_transferred   // the number of bytes written to the stream
633     );
634     @endcode
635     Regardless of whether the asynchronous operation completes
636     immediately or not, the handler will not be invoked from within
637     this function. Invocation of the handler will be performed in a
638     manner equivalent to using `net::post`.
639 
640     @see message
641 */
642 template<
643     class AsyncWriteStream,
644     bool isRequest, class Body, class Fields,
645     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
646         net::default_completion_token_t<
647             executor_type<AsyncWriteStream>>>
648 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
649 async_write(
650     AsyncWriteStream& stream,
651     message<isRequest, Body, Fields>& msg,
652     WriteHandler&& handler =
653         net::default_completion_token_t<
654             executor_type<AsyncWriteStream>>{}
655 #ifndef BOOST_BEAST_DOXYGEN
656     , typename std::enable_if<
657         is_mutable_body_writer<Body>::value>::type* = 0
658 #endif
659     );
660 
661 /** Write a complete message to a stream asynchronously.
662 
663     This function is used to write a complete message to a stream asynchronously
664     using HTTP/1. The function call always returns immediately. The asynchronous
665     operation will continue until one of the following conditions is true:
666 
667     @li The entire message is written.
668 
669     @li An error occurs.
670 
671     This operation is implemented in terms of zero or more calls to the stream's
672     `async_write_some` function, and is known as a <em>composed operation</em>.
673     The program must ensure that the stream performs no other writes
674     until this operation completes. The algorithm will use a temporary
675     @ref serializer with an empty chunk decorator to produce buffers.
676 
677     @note This function only participates in overload resolution
678     if @ref is_mutable_body_writer for <em>Body</em> returns `false`.
679 
680     @param stream The stream to which the data is to be written.
681     The type must support the <em>AsyncWriteStream</em> concept.
682 
683     @param msg The message to write.
684     The object must remain valid at least until the
685     handler is called; ownership is not transferred.
686 
687     @param handler The completion handler to invoke when the operation
688     completes. The implementation takes ownership of the handler by
689     performing a decay-copy. The equivalent function signature of
690     the handler must be:
691     @code
692     void handler(
693         error_code const& error,        // result of operation
694         std::size_t bytes_transferred   // the number of bytes written to the stream
695     );
696     @endcode
697     Regardless of whether the asynchronous operation completes
698     immediately or not, the handler will not be invoked from within
699     this function. Invocation of the handler will be performed in a
700     manner equivalent to using `net::post`.
701 
702     @see message
703 */
704 template<
705     class AsyncWriteStream,
706     bool isRequest, class Body, class Fields,
707     BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
708         net::default_completion_token_t<
709             executor_type<AsyncWriteStream>>>
710 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
711 async_write(
712     AsyncWriteStream& stream,
713     message<isRequest, Body, Fields> const& msg,
714     WriteHandler&& handler =
715         net::default_completion_token_t<
716             executor_type<AsyncWriteStream>>{}
717 #ifndef BOOST_BEAST_DOXYGEN
718     , typename std::enable_if<
719         ! is_mutable_body_writer<Body>::value>::type* = 0
720 #endif
721     );
722 
723 
724 //------------------------------------------------------------------------------
725 
726 /** Serialize an HTTP/1 header to a `std::ostream`.
727 
728     The function converts the header to its HTTP/1 serialized
729     representation and stores the result in the output stream.
730 
731     @param os The output stream to write to.
732 
733     @param msg The message fields to write.
734 */
735 template<bool isRequest, class Fields>
736 std::ostream&
737 operator<<(std::ostream& os,
738     header<isRequest, Fields> const& msg);
739 
740 /** Serialize an HTTP/1 message to a `std::ostream`.
741 
742     The function converts the message to its HTTP/1 serialized
743     representation and stores the result in the output stream.
744 
745     The implementation will automatically perform chunk encoding if
746     the contents of the message indicate that chunk encoding is required.
747 
748     @param os The output stream to write to.
749 
750     @param msg The message to write.
751 */
752 template<bool isRequest, class Body, class Fields>
753 std::ostream&
754 operator<<(std::ostream& os,
755     message<isRequest, Body, Fields> const& msg);
756 
757 } // http
758 } // beast
759 } // boost
760 
761 #include <boost/beast/http/impl/write.hpp>
762 
763 #endif
764