From 6a62e563acab96bbf73dfc0b245320d964b03ef2 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sun, 9 Oct 2016 06:34:35 -0400 Subject: [PATCH] Refine message class hierarchy: Two new objects, basic_request and basic_response, represent the portion of HTTP messages excluding the body. --- CHANGELOG.md | 11 + doc/http.qbk | 80 +++-- doc/quickref.xml | 9 +- examples/http_async_server.hpp | 14 +- examples/http_crawl.cpp | 4 +- examples/http_example.cpp | 4 +- examples/http_sync_server.hpp | 8 +- examples/ssl/http_ssl_example.cpp | 4 +- include/beast/http.hpp | 1 - include/beast/http/basic_headers.hpp | 8 +- .../http/impl/{message_v1.ipp => message.ipp} | 31 +- include/beast/http/impl/read.ipp | 8 +- include/beast/http/impl/write.ipp | 18 +- include/beast/http/message.hpp | 297 ++++++++++++++---- include/beast/http/message_v1.hpp | 139 -------- include/beast/http/parser_v1.hpp | 6 +- include/beast/http/read.hpp | 8 +- include/beast/http/write.hpp | 10 +- include/beast/websocket/impl/accept_op.ipp | 4 +- include/beast/websocket/impl/handshake_op.ipp | 6 +- include/beast/websocket/impl/response_op.ipp | 6 +- include/beast/websocket/impl/stream.ipp | 26 +- include/beast/websocket/stream.hpp | 16 +- test/Jamfile | 1 - test/http/CMakeLists.txt | 1 - test/http/message.cpp | 155 ++++++++- test/http/message_v1.cpp | 119 ------- test/http/nodejs_parser.hpp | 4 +- test/http/read.cpp | 6 +- test/http/write.cpp | 36 +-- test/websocket/stream.cpp | 2 +- 31 files changed, 566 insertions(+), 476 deletions(-) rename include/beast/http/impl/{message_v1.ipp => message.ipp} (86%) delete mode 100644 include/beast/http/message_v1.hpp delete mode 100644 test/http/message_v1.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 73ac9eb1da..b2f685f8c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,17 @@ API Changes: * Rename mask_buffer_size to write_buffer_size * Make auto_fragment a boolean option +The message class hierarchy is refactored (breaking change): + +* One message class now models both HTTP/1 and HTTP/2 messages +* message_v1, request_v1, response_v1 removed +* New classes basic_request and basic_response model + messages without the body. + + Error resolution: Callers should use message, request, + and response instead of message_v1, request_v1, and + response_v1 respectively. + -------------------------------------------------------------------------------- 1.0.0-b15 diff --git a/doc/http.qbk b/doc/http.qbk index 51e6326365..44c3ec8fdd 100644 --- a/doc/http.qbk +++ b/doc/http.qbk @@ -11,7 +11,7 @@ [block ''' - Message + Messages Headers Body Algorithms @@ -44,25 +44,25 @@ messages called responses. -[section:message Message] +[section:message Messages] -The __message__ class template models HTTP/2 requests and responses, while the -derived class __message_v1__ models HTTP/1 requests and responses, adding the -required version field. These objects are complete: they contain -all the information required to permit the algorithms to operate. These objects -are first class: They may be returned from functions, moved, copied, passed -as arguments, and stored in containers. Request and response messages are -distinct types; functions may be overloaded on just one or the other if -desired. Because this class template supports HTTP/1 and HTTP/2, it is -sometimes referred to as the universal message model. +The __message__ class template models HTTP/1 and HTTP/2 requests and responses. +These objects are complete: they contain all the information required to permit +the algorithms to operate. These objects are first class: They may be returned +from functions, moved, copied, passed as arguments, and stored in containers. +Request and response messages are distinct types; functions may be overloaded +on just one or the other if desired. Because this class template supports +HTTP/1 and HTTP/2, it is sometimes referred to as the universal message model. -These class templates have three template parameters: +There are three important template parameters in the message class: ``` - template + template< + bool isRequest, + class Body, + class Headers + > class message; - template - class message_v1; ``` * [*`isRequest`]: Controls whether or not the message is a request or response. @@ -76,28 +76,26 @@ These class templates have three template parameters: For notational convenience, the following template type aliases are provided: ``` - template>> + template< + class Body, + class Headers = basic_headers>> using request = message; - template>> + template< + class Body, + class Headers = basic_headers>> using response = message; - - template>> - using request_v1 = message_v1; - - template>> - using response_v1 = message_v1; ``` -Although these aliases have a common base class, they have different fields -depending on whether the message is a request or a response. These simplified -declarations notionally illustrate the members of HTTP/1 messages: +The message class template has different data members depending on whether +it represents a request or response. These simplified declarations +notionally illustrate the members of HTTP/1 messages: ``` template - struct request_v1 + struct request { - int version; 10 or 11 + int version; // 10 for HTTP/1.0, 11 for HTTP/1.1 std::string method; std::string url; Headers headers; @@ -105,9 +103,9 @@ declarations notionally illustrate the members of HTTP/1 messages: }; template - struct response_v1 + struct response { - int version; 10 or 11 + int version; // 10 for HTTP/1.0, 11 for HTTP/1.1 int status; std::string reason; Headers headers; @@ -117,17 +115,17 @@ declarations notionally illustrate the members of HTTP/1 messages: These statements set fields in request and response message objects: ``` - request_v1 req; + request req; + req.version = 11; // HTTP/1.1 req.method = "GET"; req.url = "/index.html"; - req.version = 11; // HTTP/1.1 req.headers.insert("User-Agent", "Beast.HTTP"); req.body = ""; - response_v1 res; + response res; + res.version = 10; // HTTP/1.0 res.status = 404; res.reason = "Not Found"; - res.version = 10; // HTTP/1.0 res.headers.insert("Server", "Beast.HTTP"); res.body = "The requested resource was not found."; ``` @@ -147,7 +145,7 @@ The field names are not case-sensitive. These statements change the values of the headers in the message passed: ``` template - void set_fields(request_v1& req) + void set_fields(request& req) { if(! req.exists("User-Agent")) req.insert("User-Agent", "myWebClient"); @@ -184,7 +182,7 @@ and serialization. Beast provides three very common [*`Body`] types: * [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body. Used in GET requests where there is no message body. Example: ``` - request_v1 req; + request req; req.version = 11; req.method = "GET"; req.url = "/index.html"; @@ -196,7 +194,7 @@ or response with simple text in the message body (such as an error message). Has the same insertion complexity of `std::string`. This is the type of body used in the examples: ``` - response_v1 res; + response res; static_assert(std::is_same::value); res.body = "Here is the data you requested"; ``` @@ -282,7 +280,7 @@ An asynchronous interface is available: ``` void handle_write(boost::system::error_code); ... - request_v1 req; + request req; ... async_write(sock, req, std::bind(&handle_write, std::placeholders::_1)); ``` @@ -297,7 +295,7 @@ stored in the streambuf parameter for use in a subsequent call to read: ``` boost::asio::streambuf sb; ... - response_v1 res; + response res; read(sock, sb, res); // Throws exception on error ... // Alternatively @@ -314,7 +312,7 @@ called: void handle_read(boost::system::error_code); ... boost::asio::streambuf sb; - response_v1 res; + response res; ... async_read(sock, res, std::bind(&handle_read, std::placeholders::_1)); ``` @@ -326,7 +324,7 @@ is optimized for performance: void handle_read(boost::system::error_code); ... beast::streambuf sb; - response_v1 res; + response res; read(sock, sb, res); ``` diff --git a/doc/quickref.xml b/doc/quickref.xml index b9c5c647c6..20c036e055 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -35,7 +35,11 @@ empty_body headers message - message_v1 + message_headers + request + request_headers + response + response_headers resume_context streambuf_body string_body @@ -60,6 +64,9 @@ async_parse async_read async_write + async_write + is_keep_alive + is_upgrade parse prepare read diff --git a/examples/http_async_server.hpp b/examples/http_async_server.hpp index bc686a8219..fdc94ef94c 100644 --- a/examples/http_async_server.hpp +++ b/examples/http_async_server.hpp @@ -32,8 +32,8 @@ class http_async_server using address_type = boost::asio::ip::address; using socket_type = boost::asio::ip::tcp::socket; - using req_type = request_v1; - using resp_type = response_v1; + using req_type = request; + using resp_type = response; std::mutex m_; bool log_ = true; @@ -94,13 +94,13 @@ class http_async_server struct data { Stream& s; - message_v1 m; + message m; Handler h; bool cont; template data(DeducedHandler&& h_, Stream& s_, - message_v1&& m_) + message&& m_) : s(s_) , m(std::move(m_)) , h(std::forward(h_)) @@ -174,7 +174,7 @@ class http_async_server class DeducedHandler> static void - async_write(Stream& stream, message_v1< + async_write(Stream& stream, message< isRequest, Body, Headers>&& msg, DeducedHandler&& handler) { @@ -236,7 +236,7 @@ class http_async_server path = server_.root_ + path; if(! boost::filesystem::exists(path)) { - response_v1 res; + response res; res.status = 404; res.reason = "Not Found"; res.version = req_.version; @@ -265,7 +265,7 @@ class http_async_server } catch(std::exception const& e) { - response_v1 res; + response res; res.status = 500; res.reason = "Internal Error"; res.version = req_.version; diff --git a/examples/http_crawl.cpp b/examples/http_crawl.cpp index 3786ca0079..262efbbd94 100644 --- a/examples/http_crawl.cpp +++ b/examples/http_crawl.cpp @@ -35,7 +35,7 @@ int main(int, char const*[]) ip::tcp::socket sock(ios); connect(sock, it); auto ep = sock.remote_endpoint(); - request_v1 req; + request req; req.method = "GET"; req.url = "/"; req.version = 11; @@ -44,7 +44,7 @@ int main(int, char const*[]) req.headers.insert("User-Agent", "beast/http"); prepare(req); write(sock, req); - response_v1 res; + response res; streambuf sb; beast::http::read(sock, sb, res); std::cout << res; diff --git a/examples/http_example.cpp b/examples/http_example.cpp index 55d74a829c..10a246d416 100644 --- a/examples/http_example.cpp +++ b/examples/http_example.cpp @@ -21,7 +21,7 @@ int main() r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"})); // Send HTTP request using beast - beast::http::request_v1 req; + beast::http::request req; req.method = "GET"; req.url = "/"; req.version = 11; @@ -32,7 +32,7 @@ int main() // Receive and print HTTP response using beast beast::streambuf sb; - beast::http::response_v1 resp; + beast::http::response resp; beast::http::read(sock, sb, resp); std::cout << resp; } diff --git a/examples/http_sync_server.hpp b/examples/http_sync_server.hpp index b9572bb7dd..271fe21bb0 100644 --- a/examples/http_sync_server.hpp +++ b/examples/http_sync_server.hpp @@ -32,8 +32,8 @@ class http_sync_server using address_type = boost::asio::ip::address; using socket_type = boost::asio::ip::tcp::socket; - using req_type = request_v1; - using resp_type = response_v1; + using req_type = request; + using resp_type = response; bool log_ = true; std::mutex m_; @@ -161,7 +161,7 @@ class http_sync_server path = root_ + path; if(! boost::filesystem::exists(path)) { - response_v1 res; + response res; res.status = 404; res.reason = "Not Found"; res.version = req.version; @@ -190,7 +190,7 @@ class http_sync_server } catch(std::exception const& e) { - response_v1 res; + response res; res.status = 500; res.reason = "Internal Error"; res.version = req.version; diff --git a/examples/ssl/http_ssl_example.cpp b/examples/ssl/http_ssl_example.cpp index e485a34bdc..bec4d6d6ab 100644 --- a/examples/ssl/http_ssl_example.cpp +++ b/examples/ssl/http_ssl_example.cpp @@ -33,7 +33,7 @@ int main() stream.handshake(ssl::stream_base::client); // Send HTTP request over SSL using Beast - beast::http::request_v1 req; + beast::http::request req; req.method = "GET"; req.url = "/"; req.version = 11; @@ -45,7 +45,7 @@ int main() // Receive and print HTTP response using Beast beast::streambuf sb; - beast::http::response_v1 resp; + beast::http::response resp; beast::http::read(stream, sb, resp); std::cout << resp; diff --git a/include/beast/http.hpp b/include/beast/http.hpp index ff7a96beb8..516dc69b31 100644 --- a/include/beast/http.hpp +++ b/include/beast/http.hpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/include/beast/http/basic_headers.hpp b/include/beast/http/basic_headers.hpp index 8972ae3435..68feb1180d 100644 --- a/include/beast/http/basic_headers.hpp +++ b/include/beast/http/basic_headers.hpp @@ -251,14 +251,14 @@ class basic_headers_base::const_iterator @note Meets the requirements of @b `FieldSequence`. */ template -class basic_headers +class basic_headers : #if ! GENERATING_DOCS - : private beast::detail::empty_base_optimization< + private beast::detail::empty_base_optimization< typename std::allocator_traits:: template rebind_alloc< - detail::basic_headers_base::element>> - , public detail::basic_headers_base + detail::basic_headers_base::element>>, #endif + public detail::basic_headers_base { using alloc_type = typename std::allocator_traits:: diff --git a/include/beast/http/impl/message_v1.ipp b/include/beast/http/impl/message.ipp similarity index 86% rename from include/beast/http/impl/message_v1.ipp rename to include/beast/http/impl/message.ipp index dafe19d687..72356aa010 100644 --- a/include/beast/http/impl/message_v1.ipp +++ b/include/beast/http/impl/message.ipp @@ -5,13 +5,14 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef BEAST_HTTP_IMPL_MESSAGE_V1_IPP -#define BEAST_HTTP_IMPL_MESSAGE_V1_IPP +#ifndef BEAST_HTTP_IMPL_MESSAGE_IPP +#define BEAST_HTTP_IMPL_MESSAGE_IPP #include #include #include #include +#include #include #include @@ -20,9 +21,10 @@ namespace http { template bool -is_keep_alive(message_v1 const& msg) +is_keep_alive(message const& msg) { - if(msg.version >= 11) + BOOST_ASSERT(msg.version == 10 || msg.version == 11); + if(msg.version == 11) { if(token_list{msg.headers["Connection"]}.exists("close")) return false; @@ -35,9 +37,10 @@ is_keep_alive(message_v1 const& msg) template bool -is_upgrade(message_v1 const& msg) +is_upgrade(message const& msg) { - if(msg.version < 11) + BOOST_ASSERT(msg.version == 10 || msg.version == 11); + if(msg.version == 10) return false; if(token_list{msg.headers["Connection"]}.exists("upgrade")) return true; @@ -56,14 +59,14 @@ template inline void prepare_options(prepare_info& pi, - message_v1& msg) + message& msg) { } template void prepare_option(prepare_info& pi, - message_v1& msg, + message& msg, connection value) { pi.connection_value = value; @@ -74,7 +77,7 @@ template< class Opt, class... Opts> void prepare_options(prepare_info& pi, - message_v1& msg, + message& msg, Opt&& opt, Opts&&... opts) { prepare_option(pi, msg, opt); @@ -85,7 +88,7 @@ prepare_options(prepare_info& pi, template void prepare_content_length(prepare_info& pi, - message_v1 const& msg, + message const& msg, std::true_type) { typename Body::writer w(msg); @@ -100,7 +103,7 @@ prepare_content_length(prepare_info& pi, template void prepare_content_length(prepare_info& pi, - message_v1 const& msg, + message const& msg, std::false_type) { pi.content_length = boost::none; @@ -112,7 +115,7 @@ template< bool isRequest, class Body, class Headers, class... Options> void -prepare(message_v1& msg, +prepare(message& msg, Options&&... options) { // VFALCO TODO @@ -143,7 +146,7 @@ prepare(message_v1& msg, struct set_field { void - operator()(message_v1& msg, + operator()(message& msg, detail::prepare_info const& pi) const { using beast::detail::ci_equal; @@ -156,7 +159,7 @@ prepare(message_v1& msg, } void - operator()(message_v1& msg, + operator()(message& msg, detail::prepare_info const& pi) const { if((msg.status / 100 ) != 1 && diff --git a/include/beast/http/impl/read.ipp b/include/beast/http/impl/read.ipp index 1c3c6bb305..eff970e68e 100644 --- a/include/beast/http/impl/read.ipp +++ b/include/beast/http/impl/read.ipp @@ -33,7 +33,7 @@ class read_op parser_v1; using message_type = - message_v1; + message; struct data { @@ -144,7 +144,7 @@ template void read(SyncReadStream& stream, DynamicBuffer& dynabuf, - message_v1& msg) + message& msg) { static_assert(is_SyncReadStream::value, "SyncReadStream requirements not met"); @@ -162,7 +162,7 @@ template void read(SyncReadStream& stream, DynamicBuffer& dynabuf, - message_v1& m, + message& m, error_code& ec) { static_assert(is_SyncReadStream::value, @@ -185,7 +185,7 @@ template::result_type async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf, - message_v1& m, + message& m, ReadHandler&& handler) { static_assert(is_AsyncReadStream::value, diff --git a/include/beast/http/impl/write.ipp b/include/beast/http/impl/write.ipp index 81df375cb9..4a5d2f4318 100644 --- a/include/beast/http/impl/write.ipp +++ b/include/beast/http/impl/write.ipp @@ -35,7 +35,7 @@ namespace detail { template void write_firstline(DynamicBuffer& dynabuf, - message_v1 const& msg) + message const& msg) { write(dynabuf, msg.method); write(dynabuf, " "); @@ -63,7 +63,7 @@ write_firstline(DynamicBuffer& dynabuf, template void write_firstline(DynamicBuffer& dynabuf, - message_v1 const& msg) + message const& msg) { switch(msg.version) { @@ -112,7 +112,7 @@ struct write_preparation using headers_type = basic_headers>; - message_v1 const& msg; + message const& msg; typename Body::writer w; streambuf sb; bool chunked; @@ -120,7 +120,7 @@ struct write_preparation explicit write_preparation( - message_v1 const& msg_) + message const& msg_) : msg(msg_) , w(msg) , chunked(token_list{ @@ -165,7 +165,7 @@ class write_op template data(DeducedHandler&& h_, Stream& s_, - message_v1 const& m_) + message const& m_) : s(s_) , wp(m_) , h(std::forward(h_)) @@ -471,7 +471,7 @@ template void write(SyncWriteStream& stream, - message_v1 const& msg) + message const& msg) { static_assert(is_SyncWriteStream::value, "SyncWriteStream requirements not met"); @@ -487,7 +487,7 @@ template void write(SyncWriteStream& stream, - message_v1 const& msg, + message const& msg, error_code& ec) { static_assert(is_SyncWriteStream::value, @@ -571,7 +571,7 @@ template::result_type async_write(AsyncWriteStream& stream, - message_v1 const& msg, + message const& msg, WriteHandler&& handler) { static_assert(is_AsyncWriteStream::value, @@ -637,7 +637,7 @@ public: template std::ostream& operator<<(std::ostream& os, - message_v1 const& msg) + message const& msg) { static_assert(is_WritableBody::value, "WritableBody requirements not met"); diff --git a/include/beast/http/message.hpp b/include/beast/http/message.hpp index 6c1a57c93f..ffb545b7d1 100644 --- a/include/beast/http/message.hpp +++ b/include/beast/http/message.hpp @@ -18,41 +18,170 @@ namespace beast { namespace http { -namespace detail { - -struct request_fields +/** A container for HTTP request headers. + + The container includes the headers, as well as the + request method and URL. Objects of this type may be + used to represent incoming or outgoing requests for + which the body is not yet known or generated. For + example, when receiving a request with the header value + "Expect: 100-continue". +*/ +template +struct request_headers { + /// The type representing the headers. + using headers_type = Headers; + + /** 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 method. std::string method; + + /// The request URI. std::string url; -protected: - void - swap(request_fields& other) + /// The HTTP headers. + Headers headers; + + request_headers() = default; + request_headers(request_headers&&) = default; + request_headers(request_headers const&) = default; + request_headers& operator=(request_headers&&) = default; + request_headers& operator=(request_headers const&) = default; + + /** Construct HTTP request headers. + + Arguments, if any, are forwarded to the constructor + of the headers member. + */ + template::type>::value>::type> + explicit + request_headers(Arg1&& arg1, ArgN&&... argn) + : headers(std::forward(arg1), + std::forward(argn)...) { - using std::swap; - swap(method, other.method); - swap(url, other.url); } }; -struct response_fields +/** Swap two HTTP request headers. + + Requirements: + + Headers is Swappable. +*/ +template +void +swap( + request_headers& a, + request_headers& b) +{ + using std::swap; + swap(a.version, b.version); + swap(a.method, b.method); + swap(a.url, b.url); + swap(a.headers, b.headers); +} + +/** A container for HTTP response headers. + + The container includes the headers, as well as the + response status and reasons. Objects of this type may + be used to represent incoming or outgoing responses for + which the body is not yet known or generated. For + example, when responding to a HEAD request. +*/ +template +struct response_headers { + /// The type representing the headers. + using headers_type = Headers; + + /** 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 response Status-Code. int status; + + /// The HTTP Reason-Phrase (obsolete). std::string reason; -protected: - void - swap(response_fields& other) + /// The HTTP headers. + Headers headers; + + response_headers() = default; + response_headers(response_headers&&) = default; + response_headers(response_headers const&) = default; + response_headers& operator=(response_headers&&) = default; + response_headers& operator=(response_headers const&) = default; + + /** Construct HTTP request headers. + + Arguments, if any, are forwarded to the constructor + of the headers member. + */ + template::type>::value>::type> + explicit + response_headers(Arg1&& arg1, ArgN&&... argn) + : headers(std::forward(arg1), + std::forward(argn)...) { - using std::swap; - swap(status, other.status); - swap(reason, other.reason); } }; -} // detail +/** Swap two HTTP response headers. -/** A HTTP message. + Requirements: + + Headers is Swappable. +*/ +template +void +swap( + response_headers& a, + response_headers& b) +{ + using std::swap; + swap(a.version, b.version); + swap(a.status, b.status); + swap(a.reason, b.reason); + swap(a.headers, b.headers); +} + +/** A container for HTTP request or response headers. +*/ +template +using message_headers = + typename std::conditional, + response_headers>::type; + +/** 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, @@ -68,37 +197,58 @@ struct response_fields @tparam Headers A type meeting the requirements of Headers. */ template -struct message - : std::conditional::type +struct message : message_headers { + /// The container used to hold the request or response headers + using base_type = message_headers; + /** The type controlling the body traits. The body member will be of type `body_type::value_type`. */ using body_type = Body; - /// The type representing the headers. - using headers_type = Headers; - /// Indicates if the message is a request. using is_request = std::integral_constant; - /// The container holding the headers. - headers_type headers; - /// A container representing the body. typename Body::value_type body; /// Default constructor message() = default; + /** Construct a message from headers. + + Additional arguments, if any, are forwarded to + the constructor of the body member. + */ + template + message(base_type&& base, Args&&... args) + : base_type(std::move(base)) + , body(std::forward(args)...) + { + } + + /** Construct a message from headers. + + Additional arguments, if any, are forwarded to + the constructor of the body member. + */ + template + 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. */ - template + template::type, base_type>::value>> explicit message(U&& u) : body(std::forward(u)) @@ -110,9 +260,11 @@ struct message @param u An argument forwarded to the body constructor. @param v An argument forwarded to the headers constructor. */ - template + template::type, base_type>::value>> message(U&& u, V&& v) - : headers(std::forward(v)) + : base_type(std::forward(v)) , body(std::forward(u)) { } @@ -126,7 +278,6 @@ struct message : message(std::piecewise_construct, un, beast::detail::make_index_sequence{}) { - } /** Construct a message. @@ -143,14 +294,7 @@ struct message { } - /// Swap this message for another message. - void - swap(message& other); - private: - using base = typename std::conditional::type; - template message(std::piecewise_construct_t, std::tuple& tu, beast::detail::index_sequence) @@ -164,31 +308,25 @@ struct message std::tuple& tu, std::tuple& tv, beast::detail::index_sequence, beast::detail::index_sequence) - : headers(std::forward(std::get(tv))...) + : base_type(std::forward(std::get(tv))...) , body(std::forward(std::get(tu))...) { } }; -template -void -message:: -swap(message& other) -{ - using std::swap; - base::swap(other); - swap(headers, other.headers); - swap(body, other.body); -} - /// Swap one message for another message. template -inline void -swap(message& lhs, - message& rhs) +swap( + message& a, + message& b) { - lhs.swap(rhs); + using std::swap; + using base_type = typename message< + isRequest, Body, Headers>::base_type; + swap(static_cast(a), + static_cast(b)); + swap(a.body, b.body); } /// A typical HTTP request @@ -201,7 +339,58 @@ template>> using response = message; +/** Returns `true` if a HTTP/1 message indicates a keep alive. + + Undefined behavior if version is greater than 11. +*/ +template +bool +is_keep_alive(message const& msg); + +/** Returns `true` if a HTTP/1 message indicates an Upgrade request or response. + + Undefined behavior if version is greater than 11. +*/ +template +bool +is_upgrade(message 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 headers of the message based on the properties of + the body and the options passed in. + + @param msg The message to prepare. The headers may be modified. + + @param options A list of prepare options. +*/ +template< + bool isRequest, class Body, class Headers, + class... Options> +void +prepare(message& msg, + Options&&... options); + } // http } // beast +#include + #endif diff --git a/include/beast/http/message_v1.hpp b/include/beast/http/message_v1.hpp deleted file mode 100644 index 418de5f118..0000000000 --- a/include/beast/http/message_v1.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// -// Copyright (c) 2013-2016 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_V1_HPP -#define BEAST_HTTP_MESSAGE_V1_HPP - -#include -#include -#include -#include - -namespace beast { -namespace http { - -/** A HTTP/1 message. - - A message can be a request or response, depending on the `isRequest` - template argument value. Requests and responses have different types, - so functions may be overloaded on them 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 is a request. - - @tparam Body A type meeting the requirements of Body. - - @tparam Headers A type meeting the requirements of Headers. -*/ -template -struct message_v1 : message -{ - /// HTTP/1 version (10 or 11) - int version; - - /// Default constructor - message_v1() = default; - - /// Constructor - template::type>::value>::type> - explicit - message_v1(Arg1&& arg1, Argn&&... argn) - : message( - std::forward(arg1), - std::forward(argn)...) - { - } - - /// Swap this message for another message. - void - swap(message_v1& other); -}; - -template -void -message_v1:: -swap(message_v1& other) -{ - using std::swap; - message::swap(other); - swap(version, other.version); -} - -/// Swap one message for another message. -template -inline -void -swap(message_v1& lhs, - message_v1& rhs) -{ - lhs.swap(rhs); -} - -/// A typical HTTP/1 request -template>> -using request_v1 = message_v1; - -/// A typical HTTP/1 response -template>> -using response_v1 = message_v1; - -/// Returns `true` if a HTTP/1 message indicates a keep alive -template -bool -is_keep_alive(message_v1 const& msg); - -/// Returns `true` if a HTTP/1 message indicates an Upgrade request or response -template -bool -is_upgrade(message_v1 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/1 message. - - This function will adjust the Content-Length, Transfer-Encoding, - and Connection headers of the message based on the properties of - the body and the options passed in. - - @param msg The message to prepare. The headers may be modified. - - @param options A list of prepare options. -*/ -template< - bool isRequest, class Body, class Headers, - class... Options> -void -prepare(message_v1& msg, - Options&&... options); - -} // http -} // beast - -#include - -#endif diff --git a/include/beast/http/parser_v1.hpp b/include/beast/http/parser_v1.hpp index 731d459541..c06180ebe0 100644 --- a/include/beast/http/parser_v1.hpp +++ b/include/beast/http/parser_v1.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -70,7 +70,7 @@ struct skip_body /** A parser for producing HTTP/1 messages. This class uses the basic HTTP/1 wire format parser to convert - a series of octets into a `message_v1`. + a series of octets into a `message`. @note A new instance of the parser is required for each message. */ @@ -84,7 +84,7 @@ class parser_v1 public: /// The type of message this parser produces. using message_type = - message_v1; + message; private: static_assert(is_ReadableBody::value, diff --git a/include/beast/http/read.hpp b/include/beast/http/read.hpp index feb38c9107..022071c635 100644 --- a/include/beast/http/read.hpp +++ b/include/beast/http/read.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace beast { namespace http { @@ -49,7 +49,7 @@ template void read(SyncReadStream& stream, DynamicBuffer& dynabuf, - message_v1& msg); + message& msg); /** Read a HTTP/1 message from a stream. @@ -85,7 +85,7 @@ template void read(SyncReadStream& stream, DynamicBuffer& dynabuf, - message_v1& msg, + message& msg, error_code& ec); /** Start an asynchronous operation to read a HTTP/1 message from a stream. @@ -136,7 +136,7 @@ typename async_completion< ReadHandler, void(error_code)>::result_type #endif async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf, - message_v1& msg, + message& msg, ReadHandler&& handler); } // http diff --git a/include/beast/http/write.hpp b/include/beast/http/write.hpp index 6d6b59172d..6bc57ad336 100644 --- a/include/beast/http/write.hpp +++ b/include/beast/http/write.hpp @@ -8,7 +8,7 @@ #ifndef BEAST_HTTP_WRITE_HPP #define BEAST_HTTP_WRITE_HPP -#include +#include #include #include #include @@ -46,7 +46,7 @@ template void write(SyncWriteStream& stream, - message_v1 const& msg); + message const& msg); /** Write a HTTP/1 message on a stream. @@ -77,7 +77,7 @@ template void write(SyncWriteStream& stream, - message_v1 const& msg, + message const& msg, error_code& ec); /** Start an asynchronous operation to write a HTTP/1 message to a stream. @@ -132,7 +132,7 @@ typename async_completion< WriteHandler, void(error_code)>::result_type #endif async_write(AsyncWriteStream& stream, - message_v1 const& msg, + message const& msg, WriteHandler&& handler); /** Serialize a HTTP/1 message to an ostream. @@ -150,7 +150,7 @@ async_write(AsyncWriteStream& stream, template std::ostream& operator<<(std::ostream& os, - message_v1 const& msg); + message const& msg); } // http } // beast diff --git a/include/beast/websocket/impl/accept_op.ipp b/include/beast/websocket/impl/accept_op.ipp index 4fb41d3c98..43ad95a042 100644 --- a/include/beast/websocket/impl/accept_op.ipp +++ b/include/beast/websocket/impl/accept_op.ipp @@ -9,7 +9,7 @@ #define BEAST_WEBSOCKET_IMPL_ACCEPT_OP_HPP #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ class stream::accept_op struct data { stream& ws; - http::request_v1 req; + http::request req; Handler h; bool cont; int state = 0; diff --git a/include/beast/websocket/impl/handshake_op.ipp b/include/beast/websocket/impl/handshake_op.ipp index 4e408b723c..2526c5df8b 100644 --- a/include/beast/websocket/impl/handshake_op.ipp +++ b/include/beast/websocket/impl/handshake_op.ipp @@ -9,7 +9,7 @@ #define BEAST_WEBSOCKET_IMPL_HANDSHAKE_OP_HPP #include -#include +#include #include #include #include @@ -33,8 +33,8 @@ class stream::handshake_op stream& ws; Handler h; std::string key; - http::request_v1 req; - http::response_v1 resp; + http::request req; + http::response resp; bool cont; int state = 0; diff --git a/include/beast/websocket/impl/response_op.ipp b/include/beast/websocket/impl/response_op.ipp index 39af5c7b47..2c9d54461c 100644 --- a/include/beast/websocket/impl/response_op.ipp +++ b/include/beast/websocket/impl/response_op.ipp @@ -8,7 +8,7 @@ #ifndef BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP #define BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP -#include +#include #include #include #include @@ -28,7 +28,7 @@ class stream::response_op struct data { stream& ws; - http::response_v1 resp; + http::response resp; Handler h; error_code final_ec; bool cont; @@ -37,7 +37,7 @@ class stream::response_op template data(DeducedHandler&& h_, stream& ws_, - http::request_v1 const& req, + http::request const& req, bool cont_) : ws(ws_) , resp(ws_.build_response(req)) diff --git a/include/beast/websocket/impl/stream.ipp b/include/beast/websocket/impl/stream.ipp index d695f01892..92fbcbd5ef 100644 --- a/include/beast/websocket/impl/stream.ipp +++ b/include/beast/websocket/impl/stream.ipp @@ -116,7 +116,7 @@ accept(ConstBufferSequence const& buffers, error_code& ec) stream_.buffer().commit(buffer_copy( stream_.buffer().prepare( buffer_size(buffers)), buffers)); - http::request_v1 m; + http::request m; http::read(next_layer(), stream_.buffer(), m, ec); if(ec) return; @@ -147,7 +147,7 @@ template template void stream:: -accept(http::request_v1 const& request) +accept(http::request const& request) { static_assert(is_SyncStream::value, "SyncStream requirements not met"); @@ -161,7 +161,7 @@ template template void stream:: -accept(http::request_v1 const& req, +accept(http::request const& req, error_code& ec) { static_assert(is_SyncStream::value, @@ -186,7 +186,7 @@ template typename async_completion< AcceptHandler, void(error_code)>::result_type stream:: -async_accept(http::request_v1 const& req, +async_accept(http::request const& req, AcceptHandler&& handler) { static_assert(is_AsyncStream::value, @@ -230,7 +230,7 @@ handshake(boost::string_ref const& host, build_request(host, resource, key), ec); if(ec) return; - http::response_v1 res; + http::response res; http::read(next_layer(), stream_.buffer(), res, ec); if(ec) return; @@ -838,12 +838,12 @@ reset() } template -http::request_v1 +http::request stream:: build_request(boost::string_ref const& host, boost::string_ref const& resource, std::string& key) { - http::request_v1 req; + http::request req; req.url = { resource.data(), resource.size() }; req.version = 11; req.method = "GET"; @@ -859,14 +859,14 @@ build_request(boost::string_ref const& host, template template -http::response_v1 +http::response stream:: -build_response(http::request_v1 const& req) +build_response(http::request const& req) { auto err = [&](std::string const& text) { - http::response_v1 res; + http::response res; res.status = 400; res.reason = http::reason_string(res.status); res.version = req.version; @@ -897,7 +897,7 @@ build_response(http::request_v1 const& req) return err("Missing Sec-WebSocket-Version"); if(version != "13") { - http::response_v1 res; + http::response res; res.status = 426; res.reason = http::reason_string(res.status); res.version = req.version; @@ -909,7 +909,7 @@ build_response(http::request_v1 const& req) return res; } } - http::response_v1 res; + http::response res; res.status = 101; res.reason = http::reason_string(res.status); res.version = req.version; @@ -930,7 +930,7 @@ template template void stream:: -do_response(http::response_v1 const& res, +do_response(http::response const& res, boost::string_ref const& key, error_code& ec) { // VFALCO Review these error codes diff --git a/include/beast/websocket/stream.hpp b/include/beast/websocket/stream.hpp index 8cc2631c88..71ef23a937 100644 --- a/include/beast/websocket/stream.hpp +++ b/include/beast/websocket/stream.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -586,7 +586,7 @@ class stream : public detail::stream_base // VFALCO TODO This should also take a DynamicBuffer with any leftover bytes. template void - accept(http::request_v1 const& request); + accept(http::request const& request); /** Respond to a WebSocket HTTP Upgrade request @@ -618,7 +618,7 @@ class stream : public detail::stream_base */ template void - accept(http::request_v1 const& request, + accept(http::request const& request, error_code& ec); /** Start responding to a WebSocket HTTP Upgrade request. @@ -669,7 +669,7 @@ class stream : public detail::stream_base typename async_completion< AcceptHandler, void(error_code)>::result_type #endif - async_accept(http::request_v1 const& request, + async_accept(http::request const& request, AcceptHandler&& handler); /** Send a HTTP WebSocket Upgrade request and receive the response. @@ -1530,18 +1530,18 @@ class stream : public detail::stream_base void reset(); - http::request_v1 + http::request build_request(boost::string_ref const& host, boost::string_ref const& resource, std::string& key); template - http::response_v1 - build_response(http::request_v1 const& req); + http::response + build_response(http::request const& req); template void - do_response(http::response_v1 const& resp, + do_response(http::response const& resp, boost::string_ref const& key, error_code& ec); void diff --git a/test/Jamfile b/test/Jamfile index 2d6378b119..41b94eac92 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -49,7 +49,6 @@ unit-test http-tests : http/empty_body.cpp http/headers.cpp http/message.cpp - http/message_v1.cpp http/parse.cpp http/parse_error.cpp http/parser_v1.cpp diff --git a/test/http/CMakeLists.txt b/test/http/CMakeLists.txt index 2e60daaa19..eb47c62823 100644 --- a/test/http/CMakeLists.txt +++ b/test/http/CMakeLists.txt @@ -18,7 +18,6 @@ add_executable (http-tests empty_body.cpp headers.cpp message.cpp - message_v1.cpp parse.cpp parse_error.cpp parser_v1.cpp diff --git a/test/http/message.cpp b/test/http/message.cpp index 68696a06c8..7f406e824a 100644 --- a/test/http/message.cpp +++ b/test/http/message.cpp @@ -8,6 +8,7 @@ // Test that header file is self-contained. #include +#include #include #include #include @@ -69,7 +70,7 @@ class message_test : public beast::unit_test::suite }; }; - void testConstruction() + void testMessage() { static_assert(std::is_constructible< message>::value, ""); @@ -125,10 +126,8 @@ class message_test : public beast::unit_test::suite BEAST_EXPECT(! h.exists("User-Agent")); BEAST_EXPECT(m.headers["User-Agent"] == "test"); } - } - void testSwap() - { + // swap message m1; message m2; m1.url = "u"; @@ -147,9 +146,154 @@ class message_test : public beast::unit_test::suite BEAST_EXPECT(m2.headers.exists("h")); } + struct MoveHeaders + { + bool moved_to = false; + bool moved_from = false; + + MoveHeaders() = default; + + MoveHeaders(MoveHeaders&& other) + : moved_to(true) + { + other.moved_from = true; + } + + MoveHeaders& operator=(MoveHeaders&& other) + { + return *this; + } + }; + + void testHeaders() + { + { + using req_type = request_headers; + static_assert(std::is_copy_constructible::value, ""); + static_assert(std::is_move_constructible::value, ""); + static_assert(std::is_copy_assignable::value, ""); + static_assert(std::is_move_assignable::value, ""); + + using res_type = response_headers; + static_assert(std::is_copy_constructible::value, ""); + static_assert(std::is_move_constructible::value, ""); + static_assert(std::is_copy_assignable::value, ""); + static_assert(std::is_move_assignable::value, ""); + } + + { + MoveHeaders h; + request_headers r{std::move(h)}; + BEAST_EXPECT(h.moved_from); + BEAST_EXPECT(r.headers.moved_to); + request m{std::move(r)}; + BEAST_EXPECT(r.headers.moved_from); + BEAST_EXPECT(m.headers.moved_to); + } + + { + MoveHeaders h; + response_headers r{std::move(h)}; + BEAST_EXPECT(h.moved_from); + BEAST_EXPECT(r.headers.moved_to); + response m{std::move(r)}; + BEAST_EXPECT(r.headers.moved_from); + BEAST_EXPECT(m.headers.moved_to); + } + } + + void testFreeFunctions() + { + { + request m; + m.method = "GET"; + m.url = "/"; + m.version = 11; + m.headers.insert("Upgrade", "test"); + BEAST_EXPECT(! is_upgrade(m)); + + prepare(m, connection::upgrade); + BEAST_EXPECT(is_upgrade(m)); + BEAST_EXPECT(m.headers["Connection"] == "upgrade"); + + m.version = 10; + BEAST_EXPECT(! is_upgrade(m)); + } + } + + void testPrepare() + { + request m; + m.version = 10; + BEAST_EXPECT(! is_upgrade(m)); + m.headers.insert("Transfer-Encoding", "chunked"); + try + { + prepare(m); + fail(); + } + catch(std::exception const&) + { + } + m.headers.erase("Transfer-Encoding"); + m.headers.insert("Content-Length", "0"); + try + { + prepare(m); + fail(); + } + catch(std::exception const&) + { + pass(); + } + m.headers.erase("Content-Length"); + m.headers.insert("Connection", "keep-alive"); + try + { + prepare(m); + fail(); + } + catch(std::exception const&) + { + pass(); + } + m.version = 11; + m.headers.erase("Connection"); + m.headers.insert("Connection", "close"); + BEAST_EXPECT(! is_keep_alive(m)); + } + + void testSwap() + { + message m1; + message m2; + m1.status = 200; + m1.version = 10; + m1.body = "1"; + m1.headers.insert("h", "v"); + m2.status = 404; + m2.reason = "OK"; + m2.body = "2"; + m2.version = 11; + swap(m1, m2); + BEAST_EXPECT(m1.status == 404); + BEAST_EXPECT(m2.status == 200); + BEAST_EXPECT(m1.reason == "OK"); + BEAST_EXPECT(m2.reason.empty()); + BEAST_EXPECT(m1.version == 11); + BEAST_EXPECT(m2.version == 10); + BEAST_EXPECT(m1.body == "2"); + BEAST_EXPECT(m2.body == "1"); + BEAST_EXPECT(! m1.headers.exists("h")); + BEAST_EXPECT(m2.headers.exists("h")); + } + void run() override { - testConstruction(); + testMessage(); + testHeaders(); + testFreeFunctions(); + testPrepare(); testSwap(); } }; @@ -158,4 +302,3 @@ BEAST_DEFINE_TESTSUITE(message,http,beast); } // http } // beast - diff --git a/test/http/message_v1.cpp b/test/http/message_v1.cpp deleted file mode 100644 index faedd42372..0000000000 --- a/test/http/message_v1.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// -// Copyright (c) 2013-2016 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) -// - -// Test that header file is self-contained. -#include - -#include -#include -#include -#include - -namespace beast { -namespace http { - -class message_v1_test : public beast::unit_test::suite -{ -public: - void testFreeFunctions() - { - { - request_v1 m; - m.method = "GET"; - m.url = "/"; - m.version = 11; - m.headers.insert("Upgrade", "test"); - BEAST_EXPECT(! is_upgrade(m)); - - prepare(m, connection::upgrade); - BEAST_EXPECT(is_upgrade(m)); - BEAST_EXPECT(m.headers["Connection"] == "upgrade"); - - m.version = 10; - BEAST_EXPECT(! is_upgrade(m)); - } - } - - void testPrepare() - { - request_v1 m; - m.version = 10; - BEAST_EXPECT(! is_upgrade(m)); - m.headers.insert("Transfer-Encoding", "chunked"); - try - { - prepare(m); - fail(); - } - catch(std::exception const&) - { - } - m.headers.erase("Transfer-Encoding"); - m.headers.insert("Content-Length", "0"); - try - { - prepare(m); - fail(); - } - catch(std::exception const&) - { - pass(); - } - m.headers.erase("Content-Length"); - m.headers.insert("Connection", "keep-alive"); - try - { - prepare(m); - fail(); - } - catch(std::exception const&) - { - pass(); - } - m.version = 11; - m.headers.erase("Connection"); - m.headers.insert("Connection", "close"); - BEAST_EXPECT(! is_keep_alive(m)); - } - - void testSwap() - { - message_v1 m1; - message_v1 m2; - m1.status = 200; - m1.version = 10; - m1.body = "1"; - m1.headers.insert("h", "v"); - m2.status = 404; - m2.reason = "OK"; - m2.body = "2"; - m2.version = 11; - swap(m1, m2); - BEAST_EXPECT(m1.status == 404); - BEAST_EXPECT(m2.status == 200); - BEAST_EXPECT(m1.reason == "OK"); - BEAST_EXPECT(m2.reason.empty()); - BEAST_EXPECT(m1.version == 11); - BEAST_EXPECT(m2.version == 10); - BEAST_EXPECT(m1.body == "2"); - BEAST_EXPECT(m2.body == "1"); - BEAST_EXPECT(! m1.headers.exists("h")); - BEAST_EXPECT(m2.headers.exists("h")); - } - - void run() override - { - testFreeFunctions(); - testPrepare(); - testSwap(); - } -}; - -BEAST_DEFINE_TESTSUITE(message_v1,http,beast); - -} // http -} // beast diff --git a/test/http/nodejs_parser.hpp b/test/http/nodejs_parser.hpp index ecde20cbcf..0adb8c124b 100644 --- a/test/http/nodejs_parser.hpp +++ b/test/http/nodejs_parser.hpp @@ -10,7 +10,7 @@ #include "nodejs-parser/http_parser.h" -#include +#include #include #include #include @@ -741,7 +741,7 @@ class nodejs_parser : public nodejs_basic_parser> { using message_type = - message_v1; + message; message_type m_; typename message_type::body_type::reader r_; diff --git a/test/http/read.cpp b/test/http/read.cpp index f3f1c32791..5a4f6d6676 100644 --- a/test/http/read.cpp +++ b/test/http/read.cpp @@ -190,7 +190,7 @@ class read_test "Content-Length: 0\r\n" "\r\n" ); - request_v1 m; + request m; try { streambuf sb; @@ -212,7 +212,7 @@ class read_test "Content-Length: 0\r\n" "\r\n" ); - request_v1 m; + request m; error_code ec; streambuf sb; read(fs, sb, m, ec); @@ -230,7 +230,7 @@ class read_test "Content-Length: 0\r\n" "\r\n" ); - request_v1 m; + request m; error_code ec; streambuf sb; async_read(fs, sb, m, do_yield[ec]); diff --git a/test/http/write.cpp b/test/http/write.cpp index f08c6b6246..bf759e16a5 100644 --- a/test/http/write.cpp +++ b/test/http/write.cpp @@ -220,7 +220,7 @@ class write_test template std::string - str(message_v1 const& m) + str(message const& m) { string_write_stream ss(ios_); write(ss, m); @@ -231,7 +231,7 @@ class write_test testAsyncWrite(yield_context do_yield) { { - message_v1 m; + message m; m.version = 10; m.status = 200; m.reason = "OK"; @@ -250,7 +250,7 @@ class write_test "*****"); } { - message_v1 m; + message m; m.version = 11; m.status = 200; m.reason = "OK"; @@ -283,7 +283,7 @@ class write_test test::fail_counter fc(n); test::fail_stream< string_write_stream> fs(fc, ios_); - message_v1 m( + message m( std::piecewise_construct, std::forward_as_tuple(fc, ios_)); m.method = "GET"; @@ -316,7 +316,7 @@ class write_test test::fail_counter fc(n); test::fail_stream< string_write_stream> fs(fc, ios_); - message_v1 m( + message m( std::piecewise_construct, std::forward_as_tuple(fc, ios_)); m.method = "GET"; @@ -351,7 +351,7 @@ class write_test test::fail_counter fc(n); test::fail_stream< string_write_stream> fs(fc, ios_); - message_v1 m( + message m( std::piecewise_construct, std::forward_as_tuple(fc, ios_)); m.method = "GET"; @@ -386,7 +386,7 @@ class write_test test::fail_counter fc(n); test::fail_stream< string_write_stream> fs(fc, ios_); - message_v1 m( + message m( std::piecewise_construct, std::forward_as_tuple(fc, ios_)); m.method = "GET"; @@ -416,7 +416,7 @@ class write_test test::fail_counter fc(n); test::fail_stream< string_write_stream> fs(fc, ios_); - message_v1 m( + message m( std::piecewise_construct, std::forward_as_tuple(fc, ios_)); m.method = "GET"; @@ -447,7 +447,7 @@ class write_test { // auto content-length HTTP/1.0 { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 10; @@ -464,7 +464,7 @@ class write_test } // keep-alive HTTP/1.0 { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 10; @@ -482,7 +482,7 @@ class write_test } // upgrade HTTP/1.0 { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 10; @@ -500,7 +500,7 @@ class write_test } // no content-length HTTP/1.0 { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 10; @@ -520,7 +520,7 @@ class write_test } // auto content-length HTTP/1.1 { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 11; @@ -537,7 +537,7 @@ class write_test } // close HTTP/1.1 { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 11; @@ -559,7 +559,7 @@ class write_test } // upgrade HTTP/1.1 { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 11; @@ -574,7 +574,7 @@ class write_test } // no content-length HTTP/1.1 { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 11; @@ -598,7 +598,7 @@ class write_test void testConvert() { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 11; @@ -611,7 +611,7 @@ class write_test void testOstream() { - message_v1 m; + message m; m.method = "GET"; m.url = "/"; m.version = 11; diff --git a/test/websocket/stream.cpp b/test/websocket/stream.cpp index 44184b10f1..d9fe641f90 100644 --- a/test/websocket/stream.cpp +++ b/test/websocket/stream.cpp @@ -184,7 +184,7 @@ class stream_test for(n = 0; n < limit; ++n) { // valid - http::request_v1 req; + http::request req; req.method = "GET"; req.url = "/"; req.version = 11;