// // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BEAST_HTTP_MESSAGE_HPP #define BEAST_HTTP_MESSAGE_HPP #include #include #include #include #include #include #include #include namespace beast { namespace http { /** A container for a HTTP request or response header. A header includes the Start Line and Fields. Some use-cases: @li When the message has no body, such as a response to a HEAD request. @li When the caller wishes to defer instantiation of the body. @li Invoke algorithms which operate on the header only. */ #if BEAST_DOXYGEN template struct header #else template struct header; template struct header #endif { /// Indicates if the header is a request or response. #if BEAST_DOXYGEN static bool constexpr is_request = isRequest; #else static bool constexpr is_request = true; #endif /// The type representing the fields. using fields_type = Fields; /** The HTTP version. This holds both the major and minor version numbers, using these formulas: @code major = version / 10; minor = version % 10; @endcode */ int version; /** Return the Request Method @note This function is only available if `isRequest == true`. */ auto method() const -> decltype(std::declval().method()) const { return fields.method(); } /** Set the Request Method @param value A value that represents the request method. @note This function is only available if `isRequest == true`. */ template void method(Value&& value) { fields.method(std::forward(value)); } /** Return the Request Target @note This function is only available if `isRequest == true`. */ auto target() const -> decltype(std::declval().target()) const { return fields.target(); } /** Set the Request Target @param value A value that represents the request method. @note This function is only available if `isRequest == true`. */ template void target(Value&& value) { fields.target(std::forward(value)); } /// The HTTP field values. fields_type fields; /// Default constructor header() = default; /// Move constructor header(header&&) = default; /// Copy constructor header(header const&) = default; /// Move assignment header& operator=(header&&) = default; /// Copy assignment header& operator=(header const&) = default; /** Construct the header. All arguments are forwarded to the constructor of the `fields` member. @note This constructor participates in overload resolution if and only if the first parameter is not convertible to `header`. */ #if BEAST_DOXYGEN template explicit header(Args&&... args); #else template 0) || ! std::is_convertible< typename std::decay::type, header>::value>::type> explicit header(Arg1&& arg1, ArgN&&... argn) : fields(std::forward(arg1), std::forward(argn)...) { } }; /** A container for a HTTP request or response header. A header includes the Start Line and Fields. Some use-cases: @li When the message has no body, such as a response to a HEAD request. @li When the caller wishes to defer instantiation of the body. @li Invoke algorithms which operate on the header only. */ template struct header { /// Indicates if the header is a request or response. static bool constexpr is_request = false; /// The type representing the fields. using fields_type = Fields; /** The HTTP version. This holds both the major and minor version numbers, using these formulas: @code major = version / 10; minor = version % 10; @endcode */ int version; /// The HTTP field values. fields_type fields; /// Default constructor header() = default; /// Move constructor header(header&&) = default; /// Copy constructor header(header const&) = default; /// Move assignment header& operator=(header&&) = default; /// Copy assignment header& operator=(header const&) = default; /** Construct the header. All arguments are forwarded to the constructor of the `fields` member. @note This constructor participates in overload resolution if and only if the first parameter is not convertible to `header`. */ template 0) || ! std::is_convertible< typename std::decay::type, header>::value>::type> explicit header(Arg1&& arg1, ArgN&&... argn) : fields(std::forward(arg1), std::forward(argn)...) { } #endif /** The Response Status-Code. @note This member is only available if `isRequest == false`. */ int status; /** Return the Reason-Phrase. The Reason-Phrase is obsolete as of rfc7230. @note This function is only available if `isRequest == false`. */ auto reason() const -> decltype(std::declval().reason()) const { return fields.reason(); } /** Set the Reason-Phrase @param value A value that represents the reason phrase. @note This function is only available if `isRequest == false`. */ template void reason(Value&& value) { fields.reason(std::forward(value)); } }; /** A container for a complete HTTP message. A message can be a request or response, depending on the `isRequest` template argument value. Requests and responses have different types; functions may be overloaded based on the type if desired. The `Body` template argument type determines the model used to read or write the content body of the message. @tparam isRequest `true` if this represents a request, or `false` if this represents a response. Some class data members are conditionally present depending on this value. @tparam Body A type meeting the requirements of Body. @tparam Fields The type of container used to hold the field value pairs. */ template struct message : header { /// The base class used to hold the header portion of the message. using base_type = header; /** The type providing the body traits. The @ref message::body member will be of type `body_type::value_type`. */ using body_type = Body; /// A value representing the body. typename Body::value_type body; /// Default constructor message() = default; /// Move constructor message(message&&) = default; /// Copy constructor message(message const&) = default; /// Move assignment message& operator=(message&&) = default; /// Copy assignment message& operator=(message const&) = default; /** Construct a message from a header. Additional arguments, if any, are forwarded to the constructor of the body member. */ template explicit message(base_type&& base, Args&&... args) : base_type(std::move(base)) , body(std::forward(args)...) { } /** Construct a message from a header. Additional arguments, if any, are forwarded to the constructor of the body member. */ template explicit message(base_type const& base, Args&&... args) : base_type(base) , body(std::forward(args)...) { } /** Construct a message. @param u An argument forwarded to the body constructor. @note This constructor participates in overload resolution only if `u` is not convertible to `base_type`. */ template::type, base_type>::value>::type #endif > explicit message(U&& u) : body(std::forward(u)) { } /** Construct a message. @param u An argument forwarded to the body constructor. @param v An argument forwarded to the fields constructor. @note This constructor participates in overload resolution only if `u` is not convertible to `base_type`. */ template::type, base_type>::value>::type #endif > message(U&& u, V&& v) : base_type(std::forward(v)) , body(std::forward(u)) { } /** Construct a message. @param un A tuple forwarded as a parameter pack to the body constructor. */ template message(std::piecewise_construct_t, std::tuple un) : message(std::piecewise_construct, un, beast::detail::make_index_sequence{}) { } /** Construct a message. @param un A tuple forwarded as a parameter pack to the body constructor. @param vn A tuple forwarded as a parameter pack to the fields constructor. */ template message(std::piecewise_construct_t, std::tuple&& un, std::tuple&& vn) : message(std::piecewise_construct, un, vn, beast::detail::make_index_sequence{}, beast::detail::make_index_sequence{}) { } /// Returns the header portion of the message base_type& base() { return *this; } /// Returns the header portion of the message base_type const& base() const { return *this; } private: template message(std::piecewise_construct_t, std::tuple& tu, beast::detail::index_sequence) : body(std::forward(std::get(tu))...) { } template message(std::piecewise_construct_t, std::tuple& tu, std::tuple& tv, beast::detail::index_sequence, beast::detail::index_sequence) : base_type(std::forward(std::get(tv))...) , body(std::forward(std::get(tu))...) { } }; /// A typical HTTP request template using request = message; /// A typical HTTP response template using response = message; //------------------------------------------------------------------------------ #if BEAST_DOXYGEN /** Swap two header objects. @par Requirements `Fields` is @b Swappable. */ template void swap( header& m1, header& m2); #endif /** Swap two message objects. @par Requirements: `Body::value_type` and `Fields` are @b Swappable. */ template void swap( message& m1, message& m2); //------------------------------------------------------------------------------ /** Returns `true` if the HTTP/1 message indicates a keep alive. Undefined behavior if version is greater than 11. */ template bool is_keep_alive(header const& msg); /** Returns `true` if the HTTP/1 message indicates an Upgrade request or response. Undefined behavior if version is greater than 11. */ template bool is_upgrade(header const& msg); /** HTTP/1 connection prepare options. @note These values are used with @ref prepare. */ enum class connection { /// Specify Connection: close. close, /// Specify Connection: keep-alive where possible. keep_alive, /// Specify Connection: upgrade. upgrade }; /** Prepare a HTTP message. This function will adjust the Content-Length, Transfer-Encoding, and Connection fields of the message based on the properties of the body and the options passed in. @param msg The message to prepare. The fields may be modified. @param options A list of prepare options. */ template< bool isRequest, class Body, class Fields, class... Options> void prepare(message& msg, Options&&... options); /** Returns the text for a known HTTP status code. */ string_view const reason_string(int status); } // http } // beast #include #endif