]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/http/message.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / http / message.hpp
1 //
2 // Copyright (c) 2016-2017 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_MESSAGE_HPP
11 #define BOOST_BEAST_HTTP_MESSAGE_HPP
12
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/http/fields.hpp>
15 #include <boost/beast/http/verb.hpp>
16 #include <boost/beast/http/status.hpp>
17 #include <boost/beast/http/type_traits.hpp>
18 #include <boost/beast/core/string.hpp>
19 #include <boost/beast/core/detail/empty_base_optimization.hpp>
20 #include <boost/beast/core/detail/integer_sequence.hpp>
21 #include <boost/assert.hpp>
22 #include <boost/optional.hpp>
23 #include <boost/throw_exception.hpp>
24 #include <memory>
25 #include <stdexcept>
26 #include <string>
27 #include <tuple>
28 #include <utility>
29
30 namespace boost {
31 namespace beast {
32 namespace http {
33
34 /** A container for an HTTP request or response header.
35
36 This container is derived from the `Fields` template type.
37 To understand all of the members of this class it is necessary
38 to view the declaration for the `Fields` type. When using
39 the default fields container, those declarations are in
40 @ref fields.
41
42 Newly constructed header objects have version set to
43 HTTP/1.1. Newly constructed response objects also have
44 result code set to @ref status::ok.
45
46 A `header` includes the start-line and header-fields.
47 */
48 #if BOOST_BEAST_DOXYGEN
49 template<bool isRequest, class Fields = fields>
50 struct header : Fields
51
52 #else
53 template<bool isRequest, class Fields = fields>
54 struct header;
55
56 template<class Fields>
57 struct header<true, Fields> : Fields
58 #endif
59 {
60 static_assert(is_fields<Fields>::value,
61 "Fields requirements not met");
62
63 /// Indicates if the header is a request or response.
64 #if BOOST_BEAST_DOXYGEN
65 using is_request = std::integral_constant<bool, isRequest>;
66 #else
67 using is_request = std::true_type;
68 #endif
69
70 /// The type representing the fields.
71 using fields_type = Fields;
72
73 /// Constructor
74 header() = default;
75
76 /// Constructor
77 header(header&&) = default;
78
79 /// Constructor
80 header(header const&) = default;
81
82 /// Assignment
83 header& operator=(header&&) = default;
84
85 /// Assignment
86 header& operator=(header const&) = default;
87
88 /** Return the HTTP-version.
89
90 This holds both the major and minor version numbers,
91 using these formulas:
92 @code
93 unsigned major = version / 10;
94 unsigned minor = version % 10;
95 @endcode
96
97 Newly constructed headers will use HTTP/1.1 by default.
98 */
99 unsigned version() const noexcept
100 {
101 return version_;
102 }
103
104 /** Set the HTTP-version.
105
106 This holds both the major and minor version numbers,
107 using these formulas:
108 @code
109 unsigned major = version / 10;
110 unsigned minor = version % 10;
111 @endcode
112
113 Newly constructed headers will use HTTP/1.1 by default.
114
115 @param value The version number to use
116 */
117 void version(unsigned value) noexcept
118 {
119 BOOST_ASSERT(value > 0 && value < 100);
120 version_ = value;
121 }
122
123 /** Return the request-method verb.
124
125 If the request-method is not one of the recognized verbs,
126 @ref verb::unknown is returned. Callers may use @ref method_string
127 to retrieve the exact text.
128
129 @note This function is only available when `isRequest == true`.
130
131 @see @ref method_string
132 */
133 verb
134 method() const;
135
136 /** Set the request-method.
137
138 This function will set the method for requests to a known verb.
139
140 @param v The request method verb to set.
141 This may not be @ref verb::unknown.
142
143 @throws std::invalid_argument when `v == verb::unknown`.
144
145 @note This function is only available when `isRequest == true`.
146 */
147 void
148 method(verb v);
149
150 /** Return the request-method as a string.
151
152 @note This function is only available when `isRequest == true`.
153
154 @see @ref method
155 */
156 string_view
157 method_string() const;
158
159 /** Set the request-method.
160
161 This function will set the request-method a known verb
162 if the string matches, otherwise it will store a copy of
163 the passed string.
164
165 @param s A string representing the request-method.
166
167 @note This function is only available when `isRequest == true`.
168 */
169 void
170 method_string(string_view s);
171
172 /** Returns the request-target string.
173
174 The request target string returned is the same string which
175 was received from the network or stored. In particular, it will
176 contain url-encoded characters and should follow the syntax
177 rules for URIs used with HTTP.
178
179 @note This function is only available when `isRequest == true`.
180 */
181 string_view
182 target() const;
183
184 /** Set the request-target string.
185
186 It is the caller's responsibility to ensure that the request
187 target string follows the syntax rules for URIs used with
188 HTTP. In particular, reserved or special characters must be
189 url-encoded. The implementation does not perform syntax checking
190 on the passed string.
191
192 @param s A string representing the request-target.
193
194 @note This function is only available when `isRequest == true`.
195 */
196 void
197 target(string_view s);
198
199 // VFALCO Don't rearrange these declarations or
200 // ifdefs, or else the documentation will break.
201
202 /** Constructor
203
204 @param args Arguments forwarded to the `Fields`
205 base class constructor.
206
207 @note This constructor participates in overload
208 resolution if and only if the first parameter is
209 not convertible to @ref header, @ref verb, or
210 @ref status.
211 */
212 #if BOOST_BEAST_DOXYGEN
213 template<class... Args>
214 explicit
215 header(Args&&... args);
216
217 #else
218 template<class Arg1, class... ArgN,
219 class = typename std::enable_if<
220 ! std::is_convertible<typename
221 std::decay<Arg1>::type, header>::value &&
222 ! std::is_convertible<typename
223 std::decay<Arg1>::type, verb>::value &&
224 ! std::is_convertible<typename
225 std::decay<Arg1>::type, header>::value
226 >::type>
227 explicit
228 header(Arg1&& arg1, ArgN&&... argn);
229
230 private:
231 template<bool, class, class>
232 friend struct message;
233
234 template<class T>
235 friend
236 void
237 swap(header<true, T>& m1, header<true, T>& m2);
238
239 template<class... FieldsArgs>
240 header(
241 verb method,
242 string_view target_,
243 unsigned version_value,
244 FieldsArgs&&... fields_args)
245 : Fields(std::forward<FieldsArgs>(fields_args)...)
246 , method_(method)
247 {
248 version(version_value);
249 target(target_);
250 }
251
252 unsigned version_ = 11;
253 verb method_ = verb::unknown;
254 };
255
256 /** A container for an HTTP request or response header.
257
258 A `header` includes the start-line and header-fields.
259 */
260 template<class Fields>
261 struct header<false, Fields> : Fields
262 {
263 static_assert(is_fields<Fields>::value,
264 "Fields requirements not met");
265
266 /// Indicates if the header is a request or response.
267 using is_request = std::false_type;
268
269 /// The type representing the fields.
270 using fields_type = Fields;
271
272 /// Constructor.
273 header() = default;
274
275 /// Constructor
276 header(header&&) = default;
277
278 /// Constructor
279 header(header const&) = default;
280
281 /// Assignment
282 header& operator=(header&&) = default;
283
284 /// Assignment
285 header& operator=(header const&) = default;
286
287 /** Constructor
288
289 @param args Arguments forwarded to the `Fields`
290 base class constructor.
291
292 @note This constructor participates in overload
293 resolution if and only if the first parameter is
294 not convertible to @ref header, @ref verb, or
295 @ref status.
296 */
297 template<class Arg1, class... ArgN,
298 class = typename std::enable_if<
299 ! std::is_convertible<typename
300 std::decay<Arg1>::type, status>::value &&
301 ! std::is_convertible<typename
302 std::decay<Arg1>::type, header>::value
303 >::type>
304 explicit
305 header(Arg1&& arg1, ArgN&&... argn);
306
307 /** Return the HTTP-version.
308
309 This holds both the major and minor version numbers,
310 using these formulas:
311 @code
312 unsigned major = version / 10;
313 unsigned minor = version % 10;
314 @endcode
315
316 Newly constructed headers will use HTTP/1.1 by default.
317 */
318 unsigned version() const noexcept
319 {
320 return version_;
321 }
322
323 /** Set the HTTP-version.
324
325 This holds both the major and minor version numbers,
326 using these formulas:
327 @code
328 unsigned major = version / 10;
329 unsigned minor = version % 10;
330 @endcode
331
332 Newly constructed headers will use HTTP/1.1 by default.
333
334 @param value The version number to use
335 */
336 void version(unsigned value) noexcept
337 {
338 BOOST_ASSERT(value > 0 && value < 100);
339 version_ = value;
340 }
341 #endif
342
343 /** The response status-code result.
344
345 If the actual status code is not a known code, this
346 function returns @ref status::unknown. Use @ref result_int
347 to return the raw status code as a number.
348
349 @note This member is only available when `isRequest == false`.
350 */
351 status
352 result() const;
353
354 /** Set the response status-code.
355
356 @param v The code to set.
357
358 @note This member is only available when `isRequest == false`.
359 */
360 void
361 result(status v);
362
363 /** Set the response status-code as an integer.
364
365 This sets the status code to the exact number passed in.
366 If the number does not correspond to one of the known
367 status codes, the function @ref result will return
368 @ref status::unknown. Use @ref result_int to obtain the
369 original raw status-code.
370
371 @param v The status-code integer to set.
372
373 @throws std::invalid_argument if `v > 999`.
374 */
375 void
376 result(unsigned v);
377
378 /** The response status-code expressed as an integer.
379
380 This returns the raw status code as an integer, even
381 when that code is not in the list of known status codes.
382
383 @note This member is only available when `isRequest == false`.
384 */
385 unsigned
386 result_int() const;
387
388 /** Return the response reason-phrase.
389
390 The reason-phrase is obsolete as of rfc7230.
391
392 @note This function is only available when `isRequest == false`.
393 */
394 string_view
395 reason() const;
396
397 /** Set the response reason-phrase (deprecated)
398
399 This function sets a custom reason-phrase to a copy of
400 the string passed in. Normally it is not necessary to set
401 the reason phrase on an outgoing response object; the
402 implementation will automatically use the standard reason
403 text for the corresponding status code.
404
405 To clear a previously set custom phrase, pass an empty
406 string. This will restore the default standard reason text
407 based on the status code used when serializing.
408
409 The reason-phrase is obsolete as of rfc7230.
410
411 @param s The string to use for the reason-phrase.
412
413 @note This function is only available when `isRequest == false`.
414 */
415 void
416 reason(string_view s);
417
418 private:
419 #if ! BOOST_BEAST_DOXYGEN
420 template<bool, class, class>
421 friend struct message;
422
423 template<class T>
424 friend
425 void
426 swap(header<false, T>& m1, header<false, T>& m2);
427
428 template<class... FieldsArgs>
429 header(
430 status result,
431 unsigned version_value,
432 FieldsArgs&&... fields_args)
433 : Fields(std::forward<FieldsArgs>(fields_args)...)
434 , result_(result)
435 {
436 version(version_value);
437 }
438
439 unsigned version_ = 11;
440 status result_ = status::ok;
441 #endif
442 };
443
444 /// A typical HTTP request header
445 template<class Fields = fields>
446 using request_header = header<true, Fields>;
447
448 /// A typical HTTP response header
449 template<class Fields = fields>
450 using response_header = header<false, Fields>;
451
452 #if defined(BOOST_MSVC)
453 // Workaround for MSVC bug with private base classes
454 namespace detail {
455 template<class T>
456 using value_type_t = typename T::value_type;
457 } // detail
458 #endif
459
460 /** A container for a complete HTTP message.
461
462 This container is derived from the `Fields` template type.
463 To understand all of the members of this class it is necessary
464 to view the declaration for the `Fields` type. When using
465 the default fields container, those declarations are in
466 @ref fields.
467
468 A message can be a request or response, depending on the
469 `isRequest` template argument value. Requests and responses
470 have different types; functions may be overloaded based on
471 the type if desired.
472
473 The `Body` template argument type determines the model used
474 to read or write the content body of the message.
475
476 Newly constructed messages objects have version set to
477 HTTP/1.1. Newly constructed response objects also have
478 result code set to @ref status::ok.
479
480 @tparam isRequest `true` if this represents a request,
481 or `false` if this represents a response. Some class data
482 members are conditionally present depending on this value.
483
484 @tparam Body A type meeting the requirements of Body.
485
486 @tparam Fields The type of container used to hold the
487 field value pairs.
488 */
489 template<bool isRequest, class Body, class Fields = fields>
490 struct message
491 : header<isRequest, Fields>
492 #if ! BOOST_BEAST_DOXYGEN
493 , beast::detail::empty_base_optimization<
494 typename Body::value_type>
495 #endif
496 {
497 /// The base class used to hold the header portion of the message.
498 using header_type = header<isRequest, Fields>;
499
500 /** The type providing the body traits.
501
502 The @ref message::body member will be of type `body_type::value_type`.
503 */
504 using body_type = Body;
505
506 /// Constructor
507 message() = default;
508
509 /// Constructor
510 message(message&&) = default;
511
512 /// Constructor
513 message(message const&) = default;
514
515 /// Assignment
516 message& operator=(message&&) = default;
517
518 /// Assignment
519 message& operator=(message const&) = default;
520
521 /** Constructor
522
523 @param h The header to move construct from.
524
525 @param body_args Optional arguments forwarded
526 to the `body` constructor.
527 */
528 template<class... BodyArgs>
529 explicit
530 message(header_type&& h, BodyArgs&&... body_args);
531
532 /** Constructor.
533
534 @param h The header to copy construct from.
535
536 @param body_args Optional arguments forwarded
537 to the `body` constructor.
538 */
539 template<class... BodyArgs>
540 explicit
541 message(header_type const& h, BodyArgs&&... body_args);
542
543 /** Constructor
544
545 @param method The request-method to use
546
547 @param target The request-target.
548
549 @param version The HTTP-version
550
551 @note This function is only available when `isRequest == true`.
552 */
553 #if BOOST_BEAST_DOXYGEN
554 message(verb method, string_view target, unsigned version);
555 #else
556 template<class Version,
557 class = typename std::enable_if<isRequest &&
558 std::is_convertible<Version, unsigned>::value>::type>
559 message(verb method, string_view target, Version version);
560 #endif
561
562 /** Constructor
563
564 @param method The request-method to use
565
566 @param target The request-target.
567
568 @param version The HTTP-version
569
570 @param body_arg An argument forwarded to the `body` constructor.
571
572 @note This function is only available when `isRequest == true`.
573 */
574 #if BOOST_BEAST_DOXYGEN
575 template<class BodyArg>
576 message(verb method, string_view target,
577 unsigned version, BodyArg&& body_arg);
578 #else
579 template<class Version, class BodyArg,
580 class = typename std::enable_if<isRequest &&
581 std::is_convertible<Version, unsigned>::value>::type>
582 message(verb method, string_view target,
583 Version version, BodyArg&& body_arg);
584 #endif
585
586 /** Constructor
587
588 @param method The request-method to use
589
590 @param target The request-target.
591
592 @param version The HTTP-version
593
594 @param body_arg An argument forwarded to the `body` constructor.
595
596 @param fields_arg An argument forwarded to the `Fields` constructor.
597
598 @note This function is only available when `isRequest == true`.
599 */
600 #if BOOST_BEAST_DOXYGEN
601 template<class BodyArg, class FieldsArg>
602 message(verb method, string_view target, unsigned version,
603 BodyArg&& body_arg, FieldsArg&& fields_arg);
604 #else
605 template<class Version, class BodyArg, class FieldsArg,
606 class = typename std::enable_if<isRequest &&
607 std::is_convertible<Version, unsigned>::value>::type>
608 message(verb method, string_view target, Version version,
609 BodyArg&& body_arg, FieldsArg&& fields_arg);
610 #endif
611
612 /** Constructor
613
614 @param result The status-code for the response
615
616 @param version The HTTP-version
617
618 @note This member is only available when `isRequest == false`.
619 */
620 #if BOOST_BEAST_DOXYGEN
621 message(status result, unsigned version);
622 #else
623 template<class Version,
624 class = typename std::enable_if<! isRequest &&
625 std::is_convertible<Version, unsigned>::value>::type>
626 message(status result, Version version);
627 #endif
628
629 /** Constructor
630
631 @param result The status-code for the response
632
633 @param version The HTTP-version
634
635 @param body_arg An argument forwarded to the `body` constructor.
636
637 @note This member is only available when `isRequest == false`.
638 */
639 #if BOOST_BEAST_DOXYGEN
640 template<class BodyArg>
641 message(status result, unsigned version, BodyArg&& body_arg);
642 #else
643 template<class Version, class BodyArg,
644 class = typename std::enable_if<! isRequest &&
645 std::is_convertible<Version, unsigned>::value>::type>
646 message(status result, Version version, BodyArg&& body_arg);
647 #endif
648
649 /** Constructor
650
651 @param result The status-code for the response
652
653 @param version The HTTP-version
654
655 @param body_arg An argument forwarded to the `body` constructor.
656
657 @param fields_arg An argument forwarded to the `Fields` base class constructor.
658
659 @note This member is only available when `isRequest == false`.
660 */
661 #if BOOST_BEAST_DOXYGEN
662 template<class BodyArg, class FieldsArg>
663 message(status result, unsigned version,
664 BodyArg&& body_arg, FieldsArg&& fields_arg);
665 #else
666 template<class Version, class BodyArg, class FieldsArg,
667 class = typename std::enable_if<! isRequest &&
668 std::is_convertible<Version, unsigned>::value>::type>
669 message(status result, Version version,
670 BodyArg&& body_arg, FieldsArg&& fields_arg);
671 #endif
672
673 /** Constructor
674
675 The header and body are default-constructed.
676 */
677 explicit
678 message(std::piecewise_construct_t);
679
680 /** Construct a message.
681
682 @param body_args A tuple forwarded as a parameter
683 pack to the body constructor.
684 */
685 template<class... BodyArgs>
686 message(std::piecewise_construct_t,
687 std::tuple<BodyArgs...> body_args);
688
689 /** Construct a message.
690
691 @param body_args A tuple forwarded as a parameter
692 pack to the body constructor.
693
694 @param fields_args A tuple forwarded as a parameter
695 pack to the `Fields` constructor.
696 */
697 template<class... BodyArgs, class... FieldsArgs>
698 message(std::piecewise_construct_t,
699 std::tuple<BodyArgs...> body_args,
700 std::tuple<FieldsArgs...> fields_args);
701
702 /// Returns the header portion of the message
703 header_type const&
704 base() const
705 {
706 return *this;
707 }
708
709 /// Returns the header portion of the message
710 header_type&
711 base()
712 {
713 return *this;
714 }
715
716 /// Returns `true` if the chunked Transfer-Encoding is specified
717 bool
718 chunked() const
719 {
720 return this->get_chunked_impl();
721 }
722
723 /** Set or clear the chunked Transfer-Encoding
724
725 This function will set or removed the "chunked" transfer
726 encoding as the last item in the list of encodings in the
727 field.
728
729 If the result of removing the chunked token results in an
730 empty string, the field is erased.
731
732 The Content-Length field is erased unconditionally.
733 */
734 void
735 chunked(bool value);
736
737 /** Returns `true` if the Content-Length field is present.
738
739 This function inspects the fields and returns `true` if
740 the Content-Length field is present. The properties of the
741 body are not checked, this only looks for the field.
742 */
743 bool
744 has_content_length() const
745 {
746 return this->has_content_length_impl();
747 }
748
749 /** Set or clear the Content-Length field
750
751 This function adjusts the Content-Length field as follows:
752
753 @li If `value` specifies a value, the Content-Length field
754 is set to the value. Otherwise
755
756 @li The Content-Length field is erased.
757
758 If "chunked" token appears as the last item in the
759 Transfer-Encoding field it is unconditionally removed.
760
761 @param value The value to set for Content-Length.
762 */
763 void
764 content_length(boost::optional<std::uint64_t> const& value);
765
766 /** Returns `true` if the message semantics indicate keep-alive
767
768 The value depends on the version in the message, which must
769 be set to the final value before this function is called or
770 else the return value is unreliable.
771 */
772 bool
773 keep_alive() const
774 {
775 return this->get_keep_alive_impl(this->version());
776 }
777
778 /** Set the keep-alive message semantic option
779
780 This function adjusts the Connection field to indicate
781 whether or not the connection should be kept open after
782 the corresponding response. The result depends on the
783 version set on the message, which must be set to the
784 final value before making this call.
785
786 @param value `true` if the connection should persist.
787 */
788 void
789 keep_alive(bool value)
790 {
791 this->set_keep_alive_impl(this->version(), value);
792 }
793
794 /** Returns `true` if the message semantics require an end of file.
795
796 For HTTP requests, this function returns the logical
797 NOT of a call to @ref keep_alive.
798
799 For HTTP responses, this function returns the logical NOT
800 of a call to @ref keep_alive if any of the following are true:
801
802 @li @ref has_content_length would return `true`
803
804 @li @ref chunked would return `true`
805
806 @li @ref result returns @ref status::no_content
807
808 @li @ref result returns @ref status::not_modified
809
810 @li @ref result returns any informational status class (100 to 199)
811
812 Otherwise, the function returns `true`.
813
814 @see https://tools.ietf.org/html/rfc7230#section-3.3
815 */
816 bool
817 need_eof() const
818 {
819 return need_eof(typename header_type::is_request{});
820 }
821
822 /** Returns the payload size of the body in octets if possible.
823
824 This function invokes the @b Body algorithm to measure
825 the number of octets in the serialized body container. If
826 there is no body, this will return zero. Otherwise, if the
827 body exists but is not known ahead of time, `boost::none`
828 is returned (usually indicating that a chunked Transfer-Encoding
829 will be used).
830
831 @note The value of the Content-Length field in the message
832 is not inspected.
833 */
834 boost::optional<std::uint64_t>
835 payload_size() const;
836
837 /** Prepare the message payload fields for the body.
838
839 This function will adjust the Content-Length and
840 Transfer-Encoding field values based on the properties
841 of the body.
842
843 @par Example
844 @code
845 request<string_body> req{verb::post, "/"};
846 req.set(field::user_agent, "Beast");
847 req.body() = "Hello, world!";
848 req.prepare_payload();
849 @endcode
850 */
851 void
852 prepare_payload()
853 {
854 prepare_payload(typename header_type::is_request{});
855 }
856
857 /// Returns the body
858 #if BOOST_BEAST_DOXYGEN || ! defined(BOOST_MSVC)
859 typename body_type::value_type&
860 #else
861 detail::value_type_t<Body>&
862 #endif
863 body()& noexcept
864 {
865 return this->member();
866 }
867
868 /// Returns the body
869 #if BOOST_BEAST_DOXYGEN || ! defined(BOOST_MSVC)
870 typename body_type::value_type&&
871 #else
872 detail::value_type_t<Body>&&
873 #endif
874 body()&& noexcept
875 {
876 return std::move(this->member());
877 }
878
879 /// Returns the body
880 #if BOOST_BEAST_DOXYGEN || ! defined(BOOST_MSVC)
881 typename body_type::value_type const&
882 #else
883 detail::value_type_t<Body> const&
884 #endif
885 body() const& noexcept
886 {
887 return this->member();
888 }
889
890 private:
891 static_assert(is_body<Body>::value,
892 "Body requirements not met");
893
894 template<
895 class... BodyArgs,
896 std::size_t... IBodyArgs>
897 message(
898 std::piecewise_construct_t,
899 std::tuple<BodyArgs...>& body_args,
900 beast::detail::index_sequence<IBodyArgs...>)
901 : beast::detail::empty_base_optimization<
902 typename Body::value_type>(
903 std::forward<BodyArgs>(
904 std::get<IBodyArgs>(body_args))...)
905 {
906 boost::ignore_unused(body_args);
907 }
908
909 template<
910 class... BodyArgs,
911 class... FieldsArgs,
912 std::size_t... IBodyArgs,
913 std::size_t... IFieldsArgs>
914 message(
915 std::piecewise_construct_t,
916 std::tuple<BodyArgs...>& body_args,
917 std::tuple<FieldsArgs...>& fields_args,
918 beast::detail::index_sequence<IBodyArgs...>,
919 beast::detail::index_sequence<IFieldsArgs...>)
920 : header_type(std::forward<FieldsArgs>(
921 std::get<IFieldsArgs>(fields_args))...)
922 , beast::detail::empty_base_optimization<
923 typename Body::value_type>(
924 std::forward<BodyArgs>(
925 std::get<IBodyArgs>(body_args))...)
926 {
927 boost::ignore_unused(body_args);
928 boost::ignore_unused(fields_args);
929 }
930
931 bool
932 need_eof(std::true_type) const
933 {
934 return ! keep_alive();
935 }
936
937 bool
938 need_eof(std::false_type) const;
939
940 boost::optional<std::uint64_t>
941 payload_size(std::true_type) const
942 {
943 return Body::size(this->body());
944 }
945
946 boost::optional<std::uint64_t>
947 payload_size(std::false_type) const
948 {
949 return boost::none;
950 }
951
952 void
953 prepare_payload(std::true_type);
954
955 void
956 prepare_payload(std::false_type);
957 };
958
959 /// A typical HTTP request
960 template<class Body, class Fields = fields>
961 using request = message<true, Body, Fields>;
962
963 /// A typical HTTP response
964 template<class Body, class Fields = fields>
965 using response = message<false, Body, Fields>;
966
967 //------------------------------------------------------------------------------
968
969 #if BOOST_BEAST_DOXYGEN
970 /** Swap two header objects.
971
972 @par Requirements
973 `Fields` is @b Swappable.
974 */
975 template<bool isRequest, class Fields>
976 void
977 swap(
978 header<isRequest, Fields>& m1,
979 header<isRequest, Fields>& m2);
980 #endif
981
982 /** Swap two message objects.
983
984 @par Requirements:
985 `Body::value_type` and `Fields` are @b Swappable.
986 */
987 template<bool isRequest, class Body, class Fields>
988 void
989 swap(
990 message<isRequest, Body, Fields>& m1,
991 message<isRequest, Body, Fields>& m2);
992
993 } // http
994 } // beast
995 } // boost
996
997 #include <boost/beast/http/impl/message.ipp>
998
999 #endif