Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:03:52

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_HTTP_MESSAGE_HPP
0011 #define BOOST_BEAST_HTTP_MESSAGE_HPP
0012 
0013 #include <boost/beast/core/detail/config.hpp>
0014 #include <boost/beast/http/fields.hpp>
0015 #include <boost/beast/http/verb.hpp>
0016 #include <boost/beast/http/status.hpp>
0017 #include <boost/beast/http/type_traits.hpp>
0018 #include <boost/beast/core/string.hpp>
0019 #include <boost/core/empty_value.hpp>
0020 #include <boost/mp11/integer_sequence.hpp>
0021 #include <boost/assert.hpp>
0022 #include <boost/optional.hpp>
0023 #include <boost/throw_exception.hpp>
0024 #include <memory>
0025 #include <stdexcept>
0026 #include <string>
0027 #include <tuple>
0028 #include <utility>
0029 
0030 namespace boost {
0031 namespace beast {
0032 namespace http {
0033 
0034 /** A container for an HTTP request or response header.
0035 
0036     This container is derived from the `Fields` template type.
0037     To understand all of the members of this class it is necessary
0038     to view the declaration for the `Fields` type. When using
0039     the default fields container, those declarations are in
0040     @ref fields.
0041 
0042     Newly constructed header objects have version set to
0043     HTTP/1.1. Newly constructed response objects also have
0044     result code set to @ref status::ok.
0045 
0046     A `header` includes the start-line and header-fields.
0047 */
0048 #if BOOST_BEAST_DOXYGEN
0049 template<bool isRequest, class Fields = fields>
0050 class header : public Fields
0051 
0052 #else
0053 template<bool isRequest, class Fields = fields>
0054 class header;
0055 
0056 template<class Fields>
0057 class header<true, Fields> : public Fields
0058 #endif
0059 {
0060 public:
0061     static_assert(is_fields<Fields>::value,
0062         "Fields type requirements not met");
0063 
0064     /// Indicates if the header is a request or response.
0065 #if BOOST_BEAST_DOXYGEN
0066     using is_request = std::integral_constant<bool, isRequest>;
0067 #else
0068     using is_request = std::true_type;
0069 #endif
0070 
0071     /// The type representing the fields.
0072     using fields_type = Fields;
0073 
0074     /// Constructor
0075     header() = default;
0076 
0077     /// Constructor
0078     header(header&&) = default;
0079 
0080     /// Constructor
0081     header(header const&) = default;
0082 
0083     /// Assignment
0084     header& operator=(header&&) = default;
0085 
0086     /// Assignment
0087     header& operator=(header const&) = default;
0088 
0089     /** Return the HTTP-version.
0090 
0091         This holds both the major and minor version numbers,
0092         using these formulas:
0093         @code
0094             unsigned major = version / 10;
0095             unsigned minor = version % 10;
0096         @endcode
0097 
0098         Newly constructed headers will use HTTP/1.1 by default.
0099     */
0100     unsigned version() const noexcept
0101     {
0102         return version_;
0103     }
0104 
0105     /** Set the HTTP-version.
0106 
0107         This holds both the major and minor version numbers,
0108         using these formulas:
0109         @code
0110             unsigned major = version / 10;
0111             unsigned minor = version % 10;
0112         @endcode
0113 
0114         Newly constructed headers will use HTTP/1.1 by default.
0115 
0116         @param value The version number to use
0117     */
0118     void version(unsigned value) noexcept
0119     {
0120         BOOST_ASSERT(value > 0 && value < 100);
0121         version_ = value;
0122     }
0123 
0124     /** Return the request-method verb.
0125 
0126         If the request-method is not one of the recognized verbs,
0127         @ref verb::unknown is returned. Callers may use @ref method_string
0128         to retrieve the exact text.
0129 
0130         @note This function is only available when `isRequest == true`.
0131 
0132         @see method_string
0133     */
0134     verb
0135     method() const;
0136 
0137     /** Set the request-method.
0138 
0139         This function will set the method for requests to a known verb.
0140 
0141         @param v The request method verb to set.
0142         This may not be @ref verb::unknown.
0143 
0144         @throws std::invalid_argument when `v == verb::unknown`.
0145 
0146         @note This function is only available when `isRequest == true`.
0147     */
0148     void
0149     method(verb v);
0150 
0151     /** Return the request-method as a string.
0152 
0153         @note This function is only available when `isRequest == true`.
0154 
0155         @see method
0156     */
0157     string_view
0158     method_string() const;
0159 
0160     /** Set the request-method.
0161 
0162         This function will set the request-method a known verb
0163         if the string matches, otherwise it will store a copy of
0164         the passed string.
0165 
0166         @param s A string representing the request-method.
0167 
0168         @note This function is only available when `isRequest == true`.
0169     */
0170     void
0171     method_string(string_view s);
0172 
0173     /** Returns the request-target string.
0174 
0175         The request target string returned is the same string which
0176         was received from the network or stored. In particular, it will
0177         contain url-encoded characters and should follow the syntax
0178         rules for URIs used with HTTP.
0179 
0180         @note This function is only available when `isRequest == true`.
0181     */
0182     string_view
0183     target() const;
0184 
0185     /** Set the request-target string.
0186 
0187         It is the caller's responsibility to ensure that the request
0188         target string follows the syntax rules for URIs used with
0189         HTTP. In particular, reserved or special characters must be
0190         url-encoded. The implementation does not perform syntax checking
0191         on the passed string.
0192 
0193         @param s A string representing the request-target.
0194 
0195         @note This function is only available when `isRequest == true`.
0196     */
0197     void
0198     target(string_view s);
0199 
0200     // VFALCO Don't rearrange these declarations or
0201     //        ifdefs, or else the documentation will break.
0202 
0203     /** Constructor
0204 
0205         @param args Arguments forwarded to the `Fields`
0206         base class constructor.
0207 
0208         @note This constructor participates in overload
0209         resolution if and only if the first parameter is
0210         not convertible to @ref header, @ref verb, or
0211         @ref status.
0212     */
0213 #if BOOST_BEAST_DOXYGEN
0214     template<class... Args>
0215     explicit
0216     header(Args&&... args);
0217 
0218 #else
0219     template<class Arg1, class... ArgN,
0220         class = typename std::enable_if<
0221             ! std::is_convertible<typename
0222                 std::decay<Arg1>::type, header>::value &&
0223             ! std::is_convertible<typename
0224                 std::decay<Arg1>::type, verb>::value &&
0225             ! std::is_convertible<typename
0226                 std::decay<Arg1>::type, status>::value
0227         >::type>
0228     explicit
0229     header(Arg1&& arg1, ArgN&&... argn);
0230 
0231 private:
0232     template<bool, class, class>
0233     friend class message;
0234 
0235     template<class T>
0236     friend
0237     void
0238     swap(header<true, T>& m1, header<true, T>& m2);
0239 
0240     template<class... FieldsArgs>
0241     header(
0242         verb method,
0243         string_view target_,
0244         unsigned version_value,
0245         FieldsArgs&&... fields_args)
0246         : Fields(std::forward<FieldsArgs>(fields_args)...)
0247         , method_(method)
0248     {
0249         version(version_value);
0250         target(target_);
0251     }
0252 
0253     unsigned version_ = 11;
0254     verb method_ = verb::unknown;
0255 };
0256 
0257 /** A container for an HTTP request or response header.
0258 
0259     A `header` includes the start-line and header-fields.
0260 */
0261 template<class Fields>
0262 class header<false, Fields> : public Fields
0263 {
0264 public:
0265     static_assert(is_fields<Fields>::value,
0266         "Fields type requirements not met");
0267 
0268     /// Indicates if the header is a request or response.
0269     using is_request = std::false_type;
0270 
0271     /// The type representing the fields.
0272     using fields_type = Fields;
0273 
0274     /// Constructor.
0275     header() = default;
0276 
0277     /// Constructor
0278     header(header&&) = default;
0279 
0280     /// Constructor
0281     header(header const&) = default;
0282 
0283     /// Assignment
0284     header& operator=(header&&) = default;
0285 
0286     /// Assignment
0287     header& operator=(header const&) = default;
0288 
0289     /** Constructor
0290 
0291         @param args Arguments forwarded to the `Fields`
0292         base class constructor.
0293 
0294         @note This constructor participates in overload
0295         resolution if and only if the first parameter is
0296         not convertible to @ref header, @ref verb, or
0297         @ref status.
0298     */
0299     template<class Arg1, class... ArgN,
0300         class = typename std::enable_if<
0301             ! std::is_convertible<typename
0302                 std::decay<Arg1>::type, header>::value &&
0303             ! std::is_convertible<typename
0304                 std::decay<Arg1>::type, verb>::value &&
0305             ! std::is_convertible<typename
0306                 std::decay<Arg1>::type, status>::value
0307         >::type>
0308     explicit
0309     header(Arg1&& arg1, ArgN&&... argn);
0310 
0311     /** Return the HTTP-version.
0312 
0313         This holds both the major and minor version numbers,
0314         using these formulas:
0315         @code
0316             unsigned major = version / 10;
0317             unsigned minor = version % 10;
0318         @endcode
0319 
0320         Newly constructed headers will use HTTP/1.1 by default.
0321     */
0322     unsigned version() const noexcept
0323     {
0324         return version_;
0325     }
0326 
0327     /** Set the HTTP-version.
0328 
0329         This holds both the major and minor version numbers,
0330         using these formulas:
0331         @code
0332             unsigned major = version / 10;
0333             unsigned minor = version % 10;
0334         @endcode
0335 
0336         Newly constructed headers will use HTTP/1.1 by default.
0337 
0338         @param value The version number to use
0339     */
0340     void version(unsigned value) noexcept
0341     {
0342         BOOST_ASSERT(value > 0 && value < 100);
0343         version_ = value;
0344     }
0345 #endif
0346 
0347     /** The response status-code result.
0348 
0349         If the actual status code is not a known code, this
0350         function returns @ref status::unknown. Use @ref result_int
0351         to return the raw status code as a number.
0352 
0353         @note This member is only available when `isRequest == false`.
0354     */
0355     status
0356     result() const;
0357 
0358     /** Set the response status-code.
0359 
0360         @param v The code to set.
0361 
0362         @note This member is only available when `isRequest == false`.
0363     */
0364     void
0365     result(status v);
0366 
0367     /** Set the response status-code as an integer.
0368 
0369         This sets the status code to the exact number passed in.
0370         If the number does not correspond to one of the known
0371         status codes, the function @ref result will return
0372         @ref status::unknown. Use @ref result_int to obtain the
0373         original raw status-code.
0374 
0375         @param v The status-code integer to set.
0376 
0377         @throws std::invalid_argument if `v > 999`.
0378     */
0379     void
0380     result(unsigned v);
0381 
0382     /** The response status-code expressed as an integer.
0383 
0384         This returns the raw status code as an integer, even
0385         when that code is not in the list of known status codes.
0386 
0387         @note This member is only available when `isRequest == false`.
0388     */
0389     unsigned
0390     result_int() const;
0391 
0392     /** Return the response reason-phrase.
0393 
0394         The reason-phrase is obsolete as of rfc7230.
0395 
0396         @note This function is only available when `isRequest == false`.
0397     */
0398     string_view
0399     reason() const;
0400 
0401     /** Set the response reason-phrase (deprecated)
0402 
0403         This function sets a custom reason-phrase to a copy of
0404         the string passed in. Normally it is not necessary to set
0405         the reason phrase on an outgoing response object; the
0406         implementation will automatically use the standard reason
0407         text for the corresponding status code.
0408 
0409         To clear a previously set custom phrase, pass an empty
0410         string. This will restore the default standard reason text
0411         based on the status code used when serializing.
0412 
0413         The reason-phrase is obsolete as of rfc7230.
0414 
0415         @param s The string to use for the reason-phrase.
0416 
0417         @note This function is only available when `isRequest == false`.
0418     */
0419     void
0420     reason(string_view s);
0421 
0422 private:
0423 #if ! BOOST_BEAST_DOXYGEN
0424     template<bool, class, class>
0425     friend class message;
0426 
0427     template<class T>
0428     friend
0429     void
0430     swap(header<false, T>& m1, header<false, T>& m2);
0431 
0432     template<class... FieldsArgs>
0433     header(
0434         status result,
0435         unsigned version_value,
0436         FieldsArgs&&... fields_args)
0437         : Fields(std::forward<FieldsArgs>(fields_args)...)
0438         , result_(result)
0439     {
0440         version(version_value);
0441     }
0442 
0443     unsigned version_ = 11;
0444     status result_ = status::ok;
0445 #endif
0446 };
0447 
0448 /// A typical HTTP request header
0449 template<class Fields = fields>
0450 using request_header = header<true, Fields>;
0451 
0452 /// A typical HTTP response header
0453 template<class Fields = fields>
0454 using response_header = header<false, Fields>;
0455 
0456 #if defined(BOOST_MSVC)
0457 // Workaround for MSVC bug with private base classes
0458 namespace detail {
0459 template<class T>
0460 using value_type_t = typename T::value_type;
0461 } // detail
0462 #endif
0463 
0464 /** A container for a complete HTTP message.
0465 
0466     This container is derived from the `Fields` template type.
0467     To understand all of the members of this class it is necessary
0468     to view the declaration for the `Fields` type. When using
0469     the default fields container, those declarations are in
0470     @ref fields.
0471 
0472     A message can be a request or response, depending on the
0473     `isRequest` template argument value. Requests and responses
0474     have different types; functions may be overloaded based on
0475     the type if desired.
0476 
0477     The `Body` template argument type determines the model used
0478     to read or write the content body of the message.
0479 
0480     Newly constructed messages objects have version set to
0481     HTTP/1.1. Newly constructed response objects also have
0482     result code set to @ref status::ok.
0483 
0484     @tparam isRequest `true` if this represents a request,
0485     or `false` if this represents a response. Some class data
0486     members are conditionally present depending on this value.
0487 
0488     @tparam Body A type meeting the requirements of Body.
0489 
0490     @tparam Fields The type of container used to hold the
0491     field value pairs.
0492 */
0493 template<bool isRequest, class Body, class Fields = fields>
0494 class message
0495     : public header<isRequest, Fields>
0496 #if ! BOOST_BEAST_DOXYGEN
0497     , boost::empty_value<
0498         typename Body::value_type>
0499 #endif
0500 {
0501 public:
0502     /// The base class used to hold the header portion of the message.
0503     using header_type = header<isRequest, Fields>;
0504 
0505     /** The type providing the body traits.
0506 
0507         The @ref message::body member will be of type `body_type::value_type`.
0508     */
0509     using body_type = Body;
0510 
0511     /// Constructor
0512     message() = default;
0513 
0514     /// Constructor
0515     message(message&&) = default;
0516 
0517     /// Constructor
0518     message(message const&) = default;
0519 
0520     /// Assignment
0521     message& operator=(message&&) = default;
0522 
0523     /// Assignment
0524     message& operator=(message const&) = default;
0525 
0526     /** Constructor
0527 
0528         @param h The header to move construct from.
0529 
0530         @param body_args Optional arguments forwarded
0531         to the `body` constructor.
0532     */
0533     template<class... BodyArgs>
0534     explicit
0535     message(header_type&& h, BodyArgs&&... body_args);
0536 
0537     /** Constructor.
0538 
0539         @param h The header to copy construct from.
0540 
0541         @param body_args Optional arguments forwarded
0542         to the `body` constructor.
0543     */
0544     template<class... BodyArgs>
0545     explicit
0546     message(header_type const& h, BodyArgs&&... body_args);
0547 
0548     /** Constructor
0549 
0550         @param method The request-method to use.
0551 
0552         @param target The request-target.
0553 
0554         @param version The HTTP-version.
0555 
0556         @note This function is only available when `isRequest == true`.
0557     */
0558 #if BOOST_BEAST_DOXYGEN
0559     message(verb method, string_view target, unsigned version);
0560 #else
0561     template<class Version,
0562         class = typename std::enable_if<isRequest &&
0563             std::is_convertible<Version, unsigned>::value>::type>
0564     message(verb method, string_view target, Version version);
0565 #endif
0566 
0567     /** Constructor
0568 
0569         @param method The request-method to use.
0570 
0571         @param target The request-target.
0572 
0573         @param version The HTTP-version.
0574 
0575         @param body_arg An argument forwarded to the `body` constructor.
0576 
0577         @note This function is only available when `isRequest == true`.
0578     */
0579 #if BOOST_BEAST_DOXYGEN
0580     template<class BodyArg>
0581     message(verb method, string_view target,
0582         unsigned version, BodyArg&& body_arg);
0583 #else
0584     template<class Version, class BodyArg,
0585         class = typename std::enable_if<isRequest &&
0586             std::is_convertible<Version, unsigned>::value>::type>
0587     message(verb method, string_view target,
0588         Version version, BodyArg&& body_arg);
0589 #endif
0590 
0591     /** Constructor
0592 
0593         @param method The request-method to use.
0594 
0595         @param target The request-target.
0596 
0597         @param version The HTTP-version.
0598 
0599         @param body_arg An argument forwarded to the `body` constructor.
0600 
0601         @param fields_arg An argument forwarded to the `Fields` constructor.
0602 
0603         @note This function is only available when `isRequest == true`.
0604     */
0605 #if BOOST_BEAST_DOXYGEN
0606     template<class BodyArg, class FieldsArg>
0607     message(verb method, string_view target, unsigned version,
0608         BodyArg&& body_arg, FieldsArg&& fields_arg);
0609 #else
0610     template<class Version, class BodyArg, class FieldsArg,
0611         class = typename std::enable_if<isRequest &&
0612             std::is_convertible<Version, unsigned>::value>::type>
0613     message(verb method, string_view target, Version version,
0614         BodyArg&& body_arg, FieldsArg&& fields_arg);
0615 #endif
0616 
0617     /** Constructor
0618 
0619         @param result The status-code for the response.
0620 
0621         @param version The HTTP-version.
0622 
0623         @note This member is only available when `isRequest == false`.
0624     */
0625 #if BOOST_BEAST_DOXYGEN
0626     message(status result, unsigned version);
0627 #else
0628     template<class Version,
0629         class = typename std::enable_if<! isRequest &&
0630            std::is_convertible<Version, unsigned>::value>::type>
0631     message(status result, Version version);
0632 #endif
0633 
0634     /** Constructor
0635 
0636         @param result The status-code for the response.
0637 
0638         @param version The HTTP-version.
0639 
0640         @param body_arg An argument forwarded to the `body` constructor.
0641 
0642         @note This member is only available when `isRequest == false`.
0643     */
0644 #if BOOST_BEAST_DOXYGEN
0645     template<class BodyArg>
0646     message(status result, unsigned version, BodyArg&& body_arg);
0647 #else
0648     template<class Version, class BodyArg,
0649         class = typename std::enable_if<! isRequest &&
0650            std::is_convertible<Version, unsigned>::value>::type>
0651     message(status result, Version version, BodyArg&& body_arg);
0652 #endif
0653 
0654     /** Constructor
0655 
0656         @param result The status-code for the response.
0657 
0658         @param version The HTTP-version.
0659 
0660         @param body_arg An argument forwarded to the `body` constructor.
0661 
0662         @param fields_arg An argument forwarded to the `Fields` base class constructor.
0663 
0664         @note This member is only available when `isRequest == false`.
0665     */
0666 #if BOOST_BEAST_DOXYGEN
0667     template<class BodyArg, class FieldsArg>
0668     message(status result, unsigned version,
0669         BodyArg&& body_arg, FieldsArg&& fields_arg);
0670 #else
0671     template<class Version, class BodyArg, class FieldsArg,
0672         class = typename std::enable_if<! isRequest &&
0673            std::is_convertible<Version, unsigned>::value>::type>
0674     message(status result, Version version,
0675         BodyArg&& body_arg, FieldsArg&& fields_arg);
0676 #endif
0677 
0678     /** Constructor
0679 
0680         The header and body are default-constructed.
0681     */
0682     explicit
0683     message(std::piecewise_construct_t);
0684 
0685     /** Construct a message.
0686 
0687         @param body_args A tuple forwarded as a parameter
0688         pack to the body constructor.
0689     */
0690     template<class... BodyArgs>
0691     message(std::piecewise_construct_t,
0692         std::tuple<BodyArgs...> body_args);
0693 
0694     /** Construct a message.
0695 
0696         @param body_args A tuple forwarded as a parameter
0697         pack to the body constructor.
0698 
0699         @param fields_args A tuple forwarded as a parameter
0700         pack to the `Fields` constructor.
0701     */
0702     template<class... BodyArgs, class... FieldsArgs>
0703     message(std::piecewise_construct_t,
0704         std::tuple<BodyArgs...> body_args,
0705         std::tuple<FieldsArgs...> fields_args);
0706 
0707     /// Returns the header portion of the message
0708     header_type const&
0709     base() const
0710     {
0711         return *this;
0712     }
0713 
0714     /// Returns the header portion of the message
0715     header_type&
0716     base()
0717     {
0718         return *this;
0719     }
0720 
0721     /// Returns `true` if the chunked Transfer-Encoding is specified
0722     bool
0723     chunked() const
0724     {
0725         return this->get_chunked_impl();
0726     }
0727 
0728     /** Set or clear the chunked Transfer-Encoding
0729 
0730         This function will set or remove the "chunked" transfer
0731         encoding as the last item in the list of encodings in the
0732         field.
0733 
0734         If the result of removing the chunked token results in an
0735         empty string, the field is erased.
0736 
0737         The Content-Length field is erased unconditionally.
0738     */
0739     void
0740     chunked(bool value);
0741 
0742     /** Returns `true` if the Content-Length field is present.
0743 
0744         This function inspects the fields and returns `true` if
0745         the Content-Length field is present. The properties of the
0746         body are not checked, this only looks for the field.
0747     */
0748     bool
0749     has_content_length() const
0750     {
0751         return this->has_content_length_impl();
0752     }
0753 
0754     /** Set or clear the Content-Length field
0755 
0756         This function adjusts the Content-Length field as follows:
0757 
0758         @li If `value` specifies a value, the Content-Length field
0759           is set to the value. Otherwise
0760 
0761         @li The Content-Length field is erased.
0762 
0763         If "chunked" token appears as the last item in the
0764         Transfer-Encoding field it is unconditionally removed.
0765 
0766         @param value The value to set for Content-Length.
0767     */
0768     void
0769     content_length(boost::optional<std::uint64_t> const& value);
0770 
0771     /** Returns `true` if the message semantics indicate keep-alive
0772 
0773         The value depends on the version in the message, which must
0774         be set to the final value before this function is called or
0775         else the return value is unreliable.
0776     */
0777     bool
0778     keep_alive() const
0779     {
0780         return this->get_keep_alive_impl(this->version());
0781     }
0782 
0783     /** Set the keep-alive message semantic option
0784 
0785         This function adjusts the Connection field to indicate
0786         whether or not the connection should be kept open after
0787         the corresponding response. The result depends on the
0788         version set on the message, which must be set to the
0789         final value before making this call.
0790 
0791         @param value `true` if the connection should persist.
0792     */
0793     void
0794     keep_alive(bool value)
0795     {
0796         this->set_keep_alive_impl(this->version(), value);
0797     }
0798 
0799     /** Returns `true` if the message semantics require an end of file.
0800 
0801         For HTTP requests, this function returns the logical
0802         NOT of a call to @ref keep_alive.
0803 
0804         For HTTP responses, this function returns the logical NOT
0805         of a call to @ref keep_alive if any of the following are true:
0806 
0807         @li @ref has_content_length would return `true`
0808 
0809         @li @ref chunked would return `true`
0810 
0811         @li @ref result returns @ref status::no_content
0812 
0813         @li @ref result returns @ref status::not_modified
0814 
0815         @li @ref result returns any informational status class (100 to 199)
0816 
0817         Otherwise, the function returns `true`.
0818 
0819         @see https://tools.ietf.org/html/rfc7230#section-3.3
0820     */
0821     bool
0822     need_eof() const
0823     {
0824         return need_eof(typename header_type::is_request{});
0825     }
0826 
0827     /** Returns the payload size of the body in octets if possible.
0828 
0829         This function invokes the <em>Body</em> algorithm to measure
0830         the number of octets in the serialized body container. If
0831         there is no body, this will return zero. Otherwise, if the
0832         body exists but is not known ahead of time, `boost::none`
0833         is returned (usually indicating that a chunked Transfer-Encoding
0834         will be used).
0835 
0836         @note The value of the Content-Length field in the message
0837         is not inspected.
0838     */
0839     boost::optional<std::uint64_t>
0840     payload_size() const;
0841 
0842     /** Prepare the message payload fields for the body.
0843 
0844         This function will adjust the Content-Length and
0845         Transfer-Encoding field values based on the properties
0846         of the body.
0847 
0848         @par Example
0849         @code
0850         request<string_body> req{verb::post, "/"};
0851         req.set(field::user_agent, "Beast");
0852         req.body() = "Hello, world!";
0853         req.prepare_payload();
0854         @endcode
0855     */
0856     void
0857     prepare_payload()
0858     {
0859         prepare_payload(typename header_type::is_request{});
0860     }
0861 
0862     /// Returns the body
0863 #if BOOST_BEAST_DOXYGEN || ! defined(BOOST_MSVC)
0864     typename body_type::value_type&
0865 #else
0866     detail::value_type_t<Body>&
0867 #endif
0868     body()& noexcept
0869     {
0870         return this->boost::empty_value<
0871             typename Body::value_type>::get();
0872     }
0873 
0874     /// Returns the body
0875 #if BOOST_BEAST_DOXYGEN || ! defined(BOOST_MSVC)
0876     typename body_type::value_type&&
0877 #else
0878     detail::value_type_t<Body>&&
0879 #endif
0880     body()&& noexcept
0881     {
0882         return std::move(
0883             this->boost::empty_value<
0884                 typename Body::value_type>::get());
0885     }
0886 
0887     /// Returns the body
0888 #if BOOST_BEAST_DOXYGEN || ! defined(BOOST_MSVC)
0889     typename body_type::value_type const&
0890 #else
0891     detail::value_type_t<Body> const&
0892 #endif
0893     body() const& noexcept
0894     {
0895         return this->boost::empty_value<
0896             typename Body::value_type>::get();
0897     }
0898 
0899 private:
0900     static_assert(is_body<Body>::value,
0901         "Body type requirements not met");
0902 
0903     template<
0904         class... BodyArgs,
0905         std::size_t... IBodyArgs>
0906     message(
0907         std::piecewise_construct_t,
0908         std::tuple<BodyArgs...>& body_args,
0909         mp11::index_sequence<IBodyArgs...>)
0910         : boost::empty_value<
0911             typename Body::value_type>(boost::empty_init_t(),
0912                 std::forward<BodyArgs>(
0913                 std::get<IBodyArgs>(body_args))...)
0914     {
0915         boost::ignore_unused(body_args);
0916     }
0917 
0918     template<
0919         class... BodyArgs,
0920         class... FieldsArgs,
0921         std::size_t... IBodyArgs,
0922         std::size_t... IFieldsArgs>
0923     message(
0924         std::piecewise_construct_t,
0925         std::tuple<BodyArgs...>& body_args,
0926         std::tuple<FieldsArgs...>& fields_args,
0927         mp11::index_sequence<IBodyArgs...>,
0928         mp11::index_sequence<IFieldsArgs...>)
0929         : header_type(std::forward<FieldsArgs>(
0930             std::get<IFieldsArgs>(fields_args))...)
0931         , boost::empty_value<
0932             typename Body::value_type>(boost::empty_init_t(),
0933                 std::forward<BodyArgs>(
0934                 std::get<IBodyArgs>(body_args))...)
0935     {
0936         boost::ignore_unused(body_args);
0937         boost::ignore_unused(fields_args);
0938     }
0939 
0940     bool
0941     need_eof(std::true_type) const
0942     {
0943         return ! keep_alive();
0944     }
0945 
0946     bool
0947     need_eof(std::false_type) const;
0948 
0949     boost::optional<std::uint64_t>
0950     payload_size(std::true_type) const
0951     {
0952         return Body::size(this->body());
0953     }
0954 
0955     boost::optional<std::uint64_t>
0956     payload_size(std::false_type) const
0957     {
0958         return boost::none;
0959     }
0960 
0961     void
0962     prepare_payload(std::true_type);
0963 
0964     void
0965     prepare_payload(std::false_type);
0966 };
0967 
0968 /// A typical HTTP request
0969 template<class Body, class Fields = fields>
0970 using request = message<true, Body, Fields>;
0971 
0972 /// A typical HTTP response
0973 template<class Body, class Fields = fields>
0974 using response = message<false, Body, Fields>;
0975 
0976 //------------------------------------------------------------------------------
0977 
0978 #if BOOST_BEAST_DOXYGEN
0979 /** Swap two header objects.
0980 
0981     @par Requirements
0982     `Fields` is @b Swappable.
0983 */
0984 template<bool isRequest, class Fields>
0985 void
0986 swap(
0987     header<isRequest, Fields>& m1,
0988     header<isRequest, Fields>& m2);
0989 #endif
0990 
0991 /** Swap two message objects.
0992 
0993     @par Requirements:
0994     `Body::value_type` and `Fields` are @b Swappable.
0995 */
0996 template<bool isRequest, class Body, class Fields>
0997 void
0998 swap(
0999     message<isRequest, Body, Fields>& m1,
1000     message<isRequest, Body, Fields>& m2);
1001 
1002 } // http
1003 } // beast
1004 } // boost
1005 
1006 #include <boost/beast/http/impl/message.hpp>
1007 
1008 #endif