Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:24:15

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