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