Refine message class hierarchy:

Two new objects, request_headers and response_headers,
represent the portion of HTTP messages excluding the body.
This commit is contained in:
Vinnie Falco
2016-10-09 06:34:35 -04:00
parent 056d6b94c2
commit a4d8a154b1
31 changed files with 569 additions and 487 deletions

View File

@ -42,6 +42,17 @@ API Changes:
* Rename mask_buffer_size to write_buffer_size * Rename mask_buffer_size to write_buffer_size
* Make auto_fragment a boolean option * 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 1.0.0-b15

View File

@ -11,7 +11,7 @@
[block ''' [block '''
<informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist> <informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist>
<member><link linkend="beast.http.message">Message</link></member> <member><link linkend="beast.http.message">Messages</link></member>
<member><link linkend="beast.http.headers">Headers</link></member> <member><link linkend="beast.http.headers">Headers</link></member>
<member><link linkend="beast.http.body">Body</link></member> <member><link linkend="beast.http.body">Body</link></member>
<member><link linkend="beast.http.algorithms">Algorithms</link></member> <member><link linkend="beast.http.algorithms">Algorithms</link></member>
@ -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 The __message__ class template models HTTP/1 and HTTP/2 requests and responses.
derived class __message_v1__ models HTTP/1 requests and responses, adding the These class templates are complete: they contain all the information needed
required version field. These objects are complete: they contain by the algorithms. Objects of this type are first class: They may be returned
all the information required to permit the algorithms to operate. These objects from functions, moved, copied, passed as arguments, and stored in containers.
are first class: They may be returned from functions, moved, copied, passed Request and response messages are distinct types; functions may be overloaded
as arguments, and stored in containers. Request and response messages are on just one or the other if desired. Because this class template supports
distinct types; functions may be overloaded on just one or the other if HTTP/1 and HTTP/2, it is sometimes referred to as the universal message model.
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<bool isRequest, class Body, class Headers> template<
bool isRequest,
class Body,
class Headers
>
class message; class message;
template<bool isRequest, class Body, class Headers>
class message_v1;
``` ```
* [*`isRequest`]: Controls whether or not the message is a request or response. * [*`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: For notational convenience, the following template type aliases are provided:
``` ```
template<class Body, class Headers = basic_headers<std::allocator<char>>> template<
class Body,
class Headers = basic_headers<std::allocator<char>>>
using request = message<true, Body, Headers>; using request = message<true, Body, Headers>;
template<class Body, class Headers = basic_headers<std::allocator<char>>> template<
class Body,
class Headers = basic_headers<std::allocator<char>>>
using response = message<false, Body, Headers>; using response = message<false, Body, Headers>;
template<class Body, class Headers = basic_headers<std::allocator<char>>>
using request_v1 = message_v1<true, Body, Headers>;
template<class Body, class Headers = basic_headers<std::allocator<char>>>
using response_v1 = message_v1<false, Body, Headers>;
``` ```
Although these aliases have a common base class, they have different fields The message class template has different data members depending on whether
depending on whether the message is a request or a response. These simplified it represents a request or response. These simplified declarations
declarations notionally illustrate the members of HTTP/1 messages: notionally illustrate the members of HTTP/1 messages:
``` ```
template<class Body, class Headers> template<class Body, class Headers>
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 method;
std::string url; std::string url;
Headers headers; Headers headers;
@ -105,9 +103,9 @@ declarations notionally illustrate the members of HTTP/1 messages:
}; };
template<class Body, class Headers> template<class Body, class Headers>
struct response_v1 struct response
{ {
int version; 10 or 11 int version; // 10 for HTTP/1.0, 11 for HTTP/1.1
int status; int status;
std::string reason; std::string reason;
Headers headers; 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: These statements set fields in request and response message objects:
``` ```
request_v1<string_body> req; request<string_body> req;
req.version = 11; // HTTP/1.1
req.method = "GET"; req.method = "GET";
req.url = "/index.html"; req.url = "/index.html";
req.version = 11; // HTTP/1.1
req.headers.insert("User-Agent", "Beast.HTTP"); req.headers.insert("User-Agent", "Beast.HTTP");
req.body = ""; req.body = "";
response_v1<string_body> res; response<string_body> res;
res.version = 10; // HTTP/1.0
res.status = 404; res.status = 404;
res.reason = "Not Found"; res.reason = "Not Found";
res.version = 10; // HTTP/1.0
res.headers.insert("Server", "Beast.HTTP"); res.headers.insert("Server", "Beast.HTTP");
res.body = "The requested resource was not found."; 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: These statements change the values of the headers in the message passed:
``` ```
template<class Body> template<class Body>
void set_fields(request_v1<Body>& req) void set_fields(request<Body>& req)
{ {
if(! req.exists("User-Agent")) if(! req.exists("User-Agent"))
req.insert("User-Agent", "myWebClient"); 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. * [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body.
Used in GET requests where there is no message body. Example: Used in GET requests where there is no message body. Example:
``` ```
request_v1<empty_body> req; request<empty_body> req;
req.version = 11; req.version = 11;
req.method = "GET"; req.method = "GET";
req.url = "/index.html"; 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 Has the same insertion complexity of `std::string`. This is the type of body
used in the examples: used in the examples:
``` ```
response_v1<string_body> res; response<string_body> res;
static_assert(std::is_same<decltype(res.body), std::string>::value); static_assert(std::is_same<decltype(res.body), std::string>::value);
res.body = "Here is the data you requested"; res.body = "Here is the data you requested";
``` ```
@ -282,7 +280,7 @@ An asynchronous interface is available:
``` ```
void handle_write(boost::system::error_code); void handle_write(boost::system::error_code);
... ...
request_v1<empty_body> req; request<empty_body> req;
... ...
async_write(sock, req, std::bind(&handle_write, std::placeholders::_1)); 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; boost::asio::streambuf sb;
... ...
response_v1<string_body> res; response<string_body> res;
read(sock, sb, res); // Throws exception on error read(sock, sb, res); // Throws exception on error
... ...
// Alternatively // Alternatively
@ -314,7 +312,7 @@ called:
void handle_read(boost::system::error_code); void handle_read(boost::system::error_code);
... ...
boost::asio::streambuf sb; boost::asio::streambuf sb;
response_v1<string_body> res; response<string_body> res;
... ...
async_read(sock, res, std::bind(&handle_read, std::placeholders::_1)); 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); void handle_read(boost::system::error_code);
... ...
beast::streambuf sb; beast::streambuf sb;
response_v1<string_body> res; response<string_body> res;
read(sock, sb, res); read(sock, sb, res);
``` ```

View File

@ -35,7 +35,11 @@
<member><link linkend="beast.ref.http__empty_body">empty_body</link></member> <member><link linkend="beast.ref.http__empty_body">empty_body</link></member>
<member><link linkend="beast.ref.http__headers">headers</link></member> <member><link linkend="beast.ref.http__headers">headers</link></member>
<member><link linkend="beast.ref.http__message">message</link></member> <member><link linkend="beast.ref.http__message">message</link></member>
<member><link linkend="beast.ref.http__message_v1">message_v1</link></member> <member><link linkend="beast.ref.http__message_headers">message_headers</link></member>
<member><link linkend="beast.ref.http__request">request</link></member>
<member><link linkend="beast.ref.http__request_headers">request_headers</link></member>
<member><link linkend="beast.ref.http__response">response</link></member>
<member><link linkend="beast.ref.http__response_headers">response_headers</link></member>
<member><link linkend="beast.ref.http__resume_context">resume_context</link></member> <member><link linkend="beast.ref.http__resume_context">resume_context</link></member>
<member><link linkend="beast.ref.http__streambuf_body">streambuf_body</link></member> <member><link linkend="beast.ref.http__streambuf_body">streambuf_body</link></member>
<member><link linkend="beast.ref.http__string_body">string_body</link></member> <member><link linkend="beast.ref.http__string_body">string_body</link></member>
@ -62,6 +66,9 @@
<member><link linkend="beast.ref.http__async_parse">async_parse</link></member> <member><link linkend="beast.ref.http__async_parse">async_parse</link></member>
<member><link linkend="beast.ref.http__async_read">async_read</link></member> <member><link linkend="beast.ref.http__async_read">async_read</link></member>
<member><link linkend="beast.ref.http__async_write">async_write</link></member> <member><link linkend="beast.ref.http__async_write">async_write</link></member>
<member><link linkend="beast.ref.http__async_write">async_write</link></member>
<member><link linkend="beast.ref.http__is_keep_alive">is_keep_alive</link></member>
<member><link linkend="beast.ref.http__is_upgrade">is_upgrade</link></member>
<member><link linkend="beast.ref.http__parse">parse</link></member> <member><link linkend="beast.ref.http__parse">parse</link></member>
<member><link linkend="beast.ref.http__prepare">prepare</link></member> <member><link linkend="beast.ref.http__prepare">prepare</link></member>
<member><link linkend="beast.ref.http__read">read</link></member> <member><link linkend="beast.ref.http__read">read</link></member>

View File

@ -32,8 +32,8 @@ class http_async_server
using address_type = boost::asio::ip::address; using address_type = boost::asio::ip::address;
using socket_type = boost::asio::ip::tcp::socket; using socket_type = boost::asio::ip::tcp::socket;
using req_type = request_v1<string_body>; using req_type = request<string_body>;
using resp_type = response_v1<file_body>; using resp_type = response<file_body>;
std::mutex m_; std::mutex m_;
bool log_ = true; bool log_ = true;
@ -94,13 +94,13 @@ private:
struct data struct data
{ {
Stream& s; Stream& s;
message_v1<isRequest, Body, Headers> m; message<isRequest, Body, Headers> m;
Handler h; Handler h;
bool cont; bool cont;
template<class DeducedHandler> template<class DeducedHandler>
data(DeducedHandler&& h_, Stream& s_, data(DeducedHandler&& h_, Stream& s_,
message_v1<isRequest, Body, Headers>&& m_) message<isRequest, Body, Headers>&& m_)
: s(s_) : s(s_)
, m(std::move(m_)) , m(std::move(m_))
, h(std::forward<DeducedHandler>(h_)) , h(std::forward<DeducedHandler>(h_))
@ -174,7 +174,7 @@ private:
class DeducedHandler> class DeducedHandler>
static static
void void
async_write(Stream& stream, message_v1< async_write(Stream& stream, message<
isRequest, Body, Headers>&& msg, isRequest, Body, Headers>&& msg,
DeducedHandler&& handler) DeducedHandler&& handler)
{ {
@ -236,7 +236,7 @@ private:
path = server_.root_ + path; path = server_.root_ + path;
if(! boost::filesystem::exists(path)) if(! boost::filesystem::exists(path))
{ {
response_v1<string_body> res; response<string_body> res;
res.status = 404; res.status = 404;
res.reason = "Not Found"; res.reason = "Not Found";
res.version = req_.version; res.version = req_.version;
@ -265,7 +265,7 @@ private:
} }
catch(std::exception const& e) catch(std::exception const& e)
{ {
response_v1<string_body> res; response<string_body> res;
res.status = 500; res.status = 500;
res.reason = "Internal Error"; res.reason = "Internal Error";
res.version = req_.version; res.version = req_.version;

View File

@ -35,7 +35,7 @@ int main(int, char const*[])
ip::tcp::socket sock(ios); ip::tcp::socket sock(ios);
connect(sock, it); connect(sock, it);
auto ep = sock.remote_endpoint(); auto ep = sock.remote_endpoint();
request_v1<empty_body> req; request<empty_body> req;
req.method = "GET"; req.method = "GET";
req.url = "/"; req.url = "/";
req.version = 11; req.version = 11;
@ -44,7 +44,7 @@ int main(int, char const*[])
req.headers.insert("User-Agent", "beast/http"); req.headers.insert("User-Agent", "beast/http");
prepare(req); prepare(req);
write(sock, req); write(sock, req);
response_v1<string_body> res; response<string_body> res;
streambuf sb; streambuf sb;
beast::http::read(sock, sb, res); beast::http::read(sock, sb, res);
std::cout << res; std::cout << res;

View File

@ -21,7 +21,7 @@ int main()
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"})); r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
// Send HTTP request using beast // Send HTTP request using beast
beast::http::request_v1<beast::http::empty_body> req; beast::http::request<beast::http::empty_body> req;
req.method = "GET"; req.method = "GET";
req.url = "/"; req.url = "/";
req.version = 11; req.version = 11;
@ -32,7 +32,7 @@ int main()
// Receive and print HTTP response using beast // Receive and print HTTP response using beast
beast::streambuf sb; beast::streambuf sb;
beast::http::response_v1<beast::http::streambuf_body> resp; beast::http::response<beast::http::streambuf_body> resp;
beast::http::read(sock, sb, resp); beast::http::read(sock, sb, resp);
std::cout << resp; std::cout << resp;
} }

View File

@ -32,8 +32,8 @@ class http_sync_server
using address_type = boost::asio::ip::address; using address_type = boost::asio::ip::address;
using socket_type = boost::asio::ip::tcp::socket; using socket_type = boost::asio::ip::tcp::socket;
using req_type = request_v1<string_body>; using req_type = request<string_body>;
using resp_type = response_v1<file_body>; using resp_type = response<file_body>;
bool log_ = true; bool log_ = true;
std::mutex m_; std::mutex m_;
@ -161,7 +161,7 @@ private:
path = root_ + path; path = root_ + path;
if(! boost::filesystem::exists(path)) if(! boost::filesystem::exists(path))
{ {
response_v1<string_body> res; response<string_body> res;
res.status = 404; res.status = 404;
res.reason = "Not Found"; res.reason = "Not Found";
res.version = req.version; res.version = req.version;
@ -190,7 +190,7 @@ private:
} }
catch(std::exception const& e) catch(std::exception const& e)
{ {
response_v1<string_body> res; response<string_body> res;
res.status = 500; res.status = 500;
res.reason = "Internal Error"; res.reason = "Internal Error";
res.version = req.version; res.version = req.version;

View File

@ -33,7 +33,7 @@ int main()
stream.handshake(ssl::stream_base::client); stream.handshake(ssl::stream_base::client);
// Send HTTP request over SSL using Beast // Send HTTP request over SSL using Beast
beast::http::request_v1<beast::http::empty_body> req; beast::http::request<beast::http::empty_body> req;
req.method = "GET"; req.method = "GET";
req.url = "/"; req.url = "/";
req.version = 11; req.version = 11;
@ -45,7 +45,7 @@ int main()
// Receive and print HTTP response using Beast // Receive and print HTTP response using Beast
beast::streambuf sb; beast::streambuf sb;
beast::http::response_v1<beast::http::streambuf_body> resp; beast::http::response<beast::http::streambuf_body> resp;
beast::http::read(stream, sb, resp); beast::http::read(stream, sb, resp);
std::cout << resp; std::cout << resp;

View File

@ -14,7 +14,6 @@
#include <beast/http/empty_body.hpp> #include <beast/http/empty_body.hpp>
#include <beast/http/headers.hpp> #include <beast/http/headers.hpp>
#include <beast/http/message.hpp> #include <beast/http/message.hpp>
#include <beast/http/message_v1.hpp>
#include <beast/http/parse.hpp> #include <beast/http/parse.hpp>
#include <beast/http/parse_error.hpp> #include <beast/http/parse_error.hpp>
#include <beast/http/parser_v1.hpp> #include <beast/http/parser_v1.hpp>

View File

@ -251,14 +251,14 @@ public:
@note Meets the requirements of @b `FieldSequence`. @note Meets the requirements of @b `FieldSequence`.
*/ */
template<class Allocator> template<class Allocator>
class basic_headers class basic_headers :
#if ! GENERATING_DOCS #if ! GENERATING_DOCS
: private beast::detail::empty_base_optimization< private beast::detail::empty_base_optimization<
typename std::allocator_traits<Allocator>:: typename std::allocator_traits<Allocator>::
template rebind_alloc< template rebind_alloc<
detail::basic_headers_base::element>> detail::basic_headers_base::element>>,
, public detail::basic_headers_base
#endif #endif
public detail::basic_headers_base
{ {
using alloc_type = typename using alloc_type = typename
std::allocator_traits<Allocator>:: std::allocator_traits<Allocator>::

View File

@ -5,13 +5,14 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#ifndef BEAST_HTTP_IMPL_MESSAGE_V1_IPP #ifndef BEAST_HTTP_IMPL_MESSAGE_IPP
#define BEAST_HTTP_IMPL_MESSAGE_V1_IPP #define BEAST_HTTP_IMPL_MESSAGE_IPP
#include <beast/core/error.hpp> #include <beast/core/error.hpp>
#include <beast/http/concepts.hpp> #include <beast/http/concepts.hpp>
#include <beast/http/rfc7230.hpp> #include <beast/http/rfc7230.hpp>
#include <beast/core/detail/ci_char_traits.hpp> #include <beast/core/detail/ci_char_traits.hpp>
#include <boost/assert.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <stdexcept> #include <stdexcept>
@ -20,9 +21,10 @@ namespace http {
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
bool bool
is_keep_alive(message_v1<isRequest, Body, Headers> const& msg) is_keep_alive(message<isRequest, Body, Headers> 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")) if(token_list{msg.headers["Connection"]}.exists("close"))
return false; return false;
@ -35,9 +37,10 @@ is_keep_alive(message_v1<isRequest, Body, Headers> const& msg)
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
bool bool
is_upgrade(message_v1<isRequest, Body, Headers> const& msg) is_upgrade(message<isRequest, Body, Headers> const& msg)
{ {
if(msg.version < 11) BOOST_ASSERT(msg.version == 10 || msg.version == 11);
if(msg.version == 10)
return false; return false;
if(token_list{msg.headers["Connection"]}.exists("upgrade")) if(token_list{msg.headers["Connection"]}.exists("upgrade"))
return true; return true;
@ -56,14 +59,14 @@ template<bool isRequest, class Body, class Headers>
inline inline
void void
prepare_options(prepare_info& pi, prepare_options(prepare_info& pi,
message_v1<isRequest, Body, Headers>& msg) message<isRequest, Body, Headers>& msg)
{ {
} }
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
void void
prepare_option(prepare_info& pi, prepare_option(prepare_info& pi,
message_v1<isRequest, Body, Headers>& msg, message<isRequest, Body, Headers>& msg,
connection value) connection value)
{ {
pi.connection_value = value; pi.connection_value = value;
@ -74,7 +77,7 @@ template<
class Opt, class... Opts> class Opt, class... Opts>
void void
prepare_options(prepare_info& pi, prepare_options(prepare_info& pi,
message_v1<isRequest, Body, Headers>& msg, message<isRequest, Body, Headers>& msg,
Opt&& opt, Opts&&... opts) Opt&& opt, Opts&&... opts)
{ {
prepare_option(pi, msg, opt); prepare_option(pi, msg, opt);
@ -85,7 +88,7 @@ prepare_options(prepare_info& pi,
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
void void
prepare_content_length(prepare_info& pi, prepare_content_length(prepare_info& pi,
message_v1<isRequest, Body, Headers> const& msg, message<isRequest, Body, Headers> const& msg,
std::true_type) std::true_type)
{ {
typename Body::writer w(msg); typename Body::writer w(msg);
@ -100,7 +103,7 @@ prepare_content_length(prepare_info& pi,
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
void void
prepare_content_length(prepare_info& pi, prepare_content_length(prepare_info& pi,
message_v1<isRequest, Body, Headers> const& msg, message<isRequest, Body, Headers> const& msg,
std::false_type) std::false_type)
{ {
pi.content_length = boost::none; pi.content_length = boost::none;
@ -112,7 +115,7 @@ template<
bool isRequest, class Body, class Headers, bool isRequest, class Body, class Headers,
class... Options> class... Options>
void void
prepare(message_v1<isRequest, Body, Headers>& msg, prepare(message<isRequest, Body, Headers>& msg,
Options&&... options) Options&&... options)
{ {
// VFALCO TODO // VFALCO TODO
@ -121,7 +124,7 @@ prepare(message_v1<isRequest, Body, Headers>& msg,
static_assert(has_writer<Body>::value, static_assert(has_writer<Body>::value,
"Body has no writer"); "Body has no writer");
static_assert(is_Writer<typename Body::writer, static_assert(is_Writer<typename Body::writer,
message_v1<isRequest, Body, Headers>>::value, message<isRequest, Body, Headers>>::value,
"Writer requirements not met"); "Writer requirements not met");
detail::prepare_info pi; detail::prepare_info pi;
detail::prepare_content_length(pi, msg, detail::prepare_content_length(pi, msg,
@ -148,7 +151,7 @@ prepare(message_v1<isRequest, Body, Headers>& msg,
struct set_field struct set_field
{ {
void void
operator()(message_v1<true, Body, Headers>& msg, operator()(message<true, Body, Headers>& msg,
detail::prepare_info const& pi) const detail::prepare_info const& pi) const
{ {
using beast::detail::ci_equal; using beast::detail::ci_equal;
@ -161,7 +164,7 @@ prepare(message_v1<isRequest, Body, Headers>& msg,
} }
void void
operator()(message_v1<false, Body, Headers>& msg, operator()(message<false, Body, Headers>& msg,
detail::prepare_info const& pi) const detail::prepare_info const& pi) const
{ {
if((msg.status / 100 ) != 1 && if((msg.status / 100 ) != 1 &&

View File

@ -33,7 +33,7 @@ class read_op
parser_v1<isRequest, Body, Headers>; parser_v1<isRequest, Body, Headers>;
using message_type = using message_type =
message_v1<isRequest, Body, Headers>; message<isRequest, Body, Headers>;
struct data struct data
{ {
@ -144,7 +144,7 @@ template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
read(SyncReadStream& stream, DynamicBuffer& dynabuf, read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg) message<isRequest, Body, Headers>& msg)
{ {
static_assert(is_SyncReadStream<SyncReadStream>::value, static_assert(is_SyncReadStream<SyncReadStream>::value,
"SyncReadStream requirements not met"); "SyncReadStream requirements not met");
@ -155,7 +155,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
static_assert(has_reader<Body>::value, static_assert(has_reader<Body>::value,
"Body has no reader"); "Body has no reader");
static_assert(is_Reader<typename Body::reader, static_assert(is_Reader<typename Body::reader,
message_v1<isRequest, Body, Headers>>::value, message<isRequest, Body, Headers>>::value,
"Reader requirements not met"); "Reader requirements not met");
error_code ec; error_code ec;
beast::http::read(stream, dynabuf, msg, ec); beast::http::read(stream, dynabuf, msg, ec);
@ -167,7 +167,7 @@ template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
read(SyncReadStream& stream, DynamicBuffer& dynabuf, read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& m, message<isRequest, Body, Headers>& m,
error_code& ec) error_code& ec)
{ {
static_assert(is_SyncReadStream<SyncReadStream>::value, static_assert(is_SyncReadStream<SyncReadStream>::value,
@ -179,7 +179,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
static_assert(has_reader<Body>::value, static_assert(has_reader<Body>::value,
"Body has no reader"); "Body has no reader");
static_assert(is_Reader<typename Body::reader, static_assert(is_Reader<typename Body::reader,
message_v1<isRequest, Body, Headers>>::value, message<isRequest, Body, Headers>>::value,
"Reader requirements not met"); "Reader requirements not met");
parser_v1<isRequest, Body, Headers> p; parser_v1<isRequest, Body, Headers> p;
beast::http::parse(stream, dynabuf, p, ec); beast::http::parse(stream, dynabuf, p, ec);
@ -195,7 +195,7 @@ template<class AsyncReadStream, class DynamicBuffer,
typename async_completion< typename async_completion<
ReadHandler, void(error_code)>::result_type ReadHandler, void(error_code)>::result_type
async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf, async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& m, message<isRequest, Body, Headers>& m,
ReadHandler&& handler) ReadHandler&& handler)
{ {
static_assert(is_AsyncReadStream<AsyncReadStream>::value, static_assert(is_AsyncReadStream<AsyncReadStream>::value,
@ -207,7 +207,7 @@ async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
static_assert(has_reader<Body>::value, static_assert(has_reader<Body>::value,
"Body has no reader"); "Body has no reader");
static_assert(is_Reader<typename Body::reader, static_assert(is_Reader<typename Body::reader,
message_v1<isRequest, Body, Headers>>::value, message<isRequest, Body, Headers>>::value,
"Reader requirements not met"); "Reader requirements not met");
beast::async_completion<ReadHandler, beast::async_completion<ReadHandler,
void(error_code)> completion(handler); void(error_code)> completion(handler);

View File

@ -34,7 +34,7 @@ namespace detail {
template<class DynamicBuffer, class Body, class Headers> template<class DynamicBuffer, class Body, class Headers>
void void
write_firstline(DynamicBuffer& dynabuf, write_firstline(DynamicBuffer& dynabuf,
message_v1<true, Body, Headers> const& msg) message<true, Body, Headers> const& msg)
{ {
write(dynabuf, msg.method); write(dynabuf, msg.method);
write(dynabuf, " "); write(dynabuf, " ");
@ -62,7 +62,7 @@ write_firstline(DynamicBuffer& dynabuf,
template<class DynamicBuffer, class Body, class Headers> template<class DynamicBuffer, class Body, class Headers>
void void
write_firstline(DynamicBuffer& dynabuf, write_firstline(DynamicBuffer& dynabuf,
message_v1<false, Body, Headers> const& msg) message<false, Body, Headers> const& msg)
{ {
switch(msg.version) switch(msg.version)
{ {
@ -108,7 +108,7 @@ write_fields(DynamicBuffer& dynabuf, FieldSequence const& fields)
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
struct write_preparation struct write_preparation
{ {
message_v1<isRequest, Body, Headers> const& msg; message<isRequest, Body, Headers> const& msg;
typename Body::writer w; typename Body::writer w;
streambuf sb; streambuf sb;
bool chunked; bool chunked;
@ -116,7 +116,7 @@ struct write_preparation
explicit explicit
write_preparation( write_preparation(
message_v1<isRequest, Body, Headers> const& msg_) message<isRequest, Body, Headers> const& msg_)
: msg(msg_) : msg(msg_)
, w(msg) , w(msg)
, chunked(token_list{ , chunked(token_list{
@ -161,7 +161,7 @@ class write_op
template<class DeducedHandler> template<class DeducedHandler>
data(DeducedHandler&& h_, Stream& s_, data(DeducedHandler&& h_, Stream& s_,
message_v1<isRequest, Body, Headers> const& m_) message<isRequest, Body, Headers> const& m_)
: s(s_) : s(s_)
, wp(m_) , wp(m_)
, h(std::forward<DeducedHandler>(h_)) , h(std::forward<DeducedHandler>(h_))
@ -467,7 +467,7 @@ template<class SyncWriteStream,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
write(SyncWriteStream& stream, write(SyncWriteStream& stream,
message_v1<isRequest, Body, Headers> const& msg) message<isRequest, Body, Headers> const& msg)
{ {
static_assert(is_SyncWriteStream<SyncWriteStream>::value, static_assert(is_SyncWriteStream<SyncWriteStream>::value,
"SyncWriteStream requirements not met"); "SyncWriteStream requirements not met");
@ -476,7 +476,7 @@ write(SyncWriteStream& stream,
static_assert(has_writer<Body>::value, static_assert(has_writer<Body>::value,
"Body has no writer"); "Body has no writer");
static_assert(is_Writer<typename Body::writer, static_assert(is_Writer<typename Body::writer,
message_v1<isRequest, Body, Headers>>::value, message<isRequest, Body, Headers>>::value,
"Writer requirements not met"); "Writer requirements not met");
error_code ec; error_code ec;
write(stream, msg, ec); write(stream, msg, ec);
@ -488,7 +488,7 @@ template<class SyncWriteStream,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
write(SyncWriteStream& stream, write(SyncWriteStream& stream,
message_v1<isRequest, Body, Headers> const& msg, message<isRequest, Body, Headers> const& msg,
error_code& ec) error_code& ec)
{ {
static_assert(is_SyncWriteStream<SyncWriteStream>::value, static_assert(is_SyncWriteStream<SyncWriteStream>::value,
@ -498,7 +498,7 @@ write(SyncWriteStream& stream,
static_assert(has_writer<Body>::value, static_assert(has_writer<Body>::value,
"Body has no writer"); "Body has no writer");
static_assert(is_Writer<typename Body::writer, static_assert(is_Writer<typename Body::writer,
message_v1<isRequest, Body, Headers>>::value, message<isRequest, Body, Headers>>::value,
"Writer requirements not met"); "Writer requirements not met");
detail::write_preparation<isRequest, Body, Headers> wp(msg); detail::write_preparation<isRequest, Body, Headers> wp(msg);
wp.init(ec); wp.init(ec);
@ -584,7 +584,7 @@ template<class AsyncWriteStream,
typename async_completion< typename async_completion<
WriteHandler, void(error_code)>::result_type WriteHandler, void(error_code)>::result_type
async_write(AsyncWriteStream& stream, async_write(AsyncWriteStream& stream,
message_v1<isRequest, Body, Headers> const& msg, message<isRequest, Body, Headers> const& msg,
WriteHandler&& handler) WriteHandler&& handler)
{ {
static_assert(is_AsyncWriteStream<AsyncWriteStream>::value, static_assert(is_AsyncWriteStream<AsyncWriteStream>::value,
@ -594,7 +594,7 @@ async_write(AsyncWriteStream& stream,
static_assert(has_writer<Body>::value, static_assert(has_writer<Body>::value,
"Body has no writer"); "Body has no writer");
static_assert(is_Writer<typename Body::writer, static_assert(is_Writer<typename Body::writer,
message_v1<isRequest, Body, Headers>>::value, message<isRequest, Body, Headers>>::value,
"Writer requirements not met"); "Writer requirements not met");
beast::async_completion<WriteHandler, beast::async_completion<WriteHandler,
void(error_code)> completion(handler); void(error_code)> completion(handler);
@ -655,14 +655,14 @@ public:
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
std::ostream& std::ostream&
operator<<(std::ostream& os, operator<<(std::ostream& os,
message_v1<isRequest, Body, Headers> const& msg) message<isRequest, Body, Headers> const& msg)
{ {
static_assert(is_Body<Body>::value, static_assert(is_Body<Body>::value,
"Body requirements not met"); "Body requirements not met");
static_assert(has_writer<Body>::value, static_assert(has_writer<Body>::value,
"Body has no writer"); "Body has no writer");
static_assert(is_Writer<typename Body::writer, static_assert(is_Writer<typename Body::writer,
message_v1<isRequest, Body, Headers>>::value, message<isRequest, Body, Headers>>::value,
"Writer requirements not met"); "Writer requirements not met");
detail::ostream_SyncStream oss(os); detail::ostream_SyncStream oss(os);
error_code ec; error_code ec;

View File

@ -18,41 +18,174 @@
namespace beast { namespace beast {
namespace http { namespace http {
namespace detail { /** A container for HTTP request headers.
struct request_fields 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<class Headers>
struct request_headers
{ {
/// Indicates if the message is a request.
using is_request =
std::integral_constant<bool, true>;
/// 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; std::string method;
/// The request URI.
std::string url; std::string url;
protected: /// The HTTP headers.
void Headers headers;
swap(request_fields& other)
/** Construct HTTP request headers.
Arguments, if any, are forwarded to the constructor
of the headers member.
*/
/** @{ */
request_headers() = default;
template<class Arg1, class... ArgN,
class = typename std::enable_if<
(sizeof...(ArgN) > 0) || ! std::is_convertible<
typename std::decay<Arg1>::type,
request_headers>::value>::type>
explicit
request_headers(Arg1&& arg1, ArgN&&... argn)
: headers(std::forward<Arg1>(arg1),
std::forward<ArgN>(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<class Headers>
void
swap(
request_headers<Headers>& a,
request_headers<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<class Headers>
struct response_headers
{
/// Indicates if the message is a response.
using is_request =
std::integral_constant<bool, false>;
/// 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; int status;
/// The HTTP Reason-Phrase (obsolete).
std::string reason; std::string reason;
protected: /// The HTTP headers.
void Headers headers;
swap(response_fields& other)
/** Construct HTTP request headers.
Arguments, if any, are forwarded to the constructor
of the headers member.
*/
/** @{ */
response_headers() = default;
template<class Arg1, class... ArgN,
class = typename std::enable_if<
(sizeof...(ArgN) > 0) || ! std::is_convertible<
typename std::decay<Arg1>::type,
response_headers>::value>::type>
explicit
response_headers(Arg1&& arg1, ArgN&&... argn)
: headers(std::forward<Arg1>(arg1),
std::forward<ArgN>(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<class Headers>
void
swap(
response_headers<Headers>& a,
response_headers<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<bool isRequest, class Headers>
using message_headers =
typename std::conditional<isRequest,
request_headers<Headers>,
response_headers<Headers>>::type;
/** A complete HTTP message.
A message can be a request or response, depending on the `isRequest` A message can be a request or response, depending on the `isRequest`
template argument value. Requests and responses have different types, template argument value. Requests and responses have different types,
@ -68,37 +201,56 @@ protected:
@tparam Headers A type meeting the requirements of Headers. @tparam Headers A type meeting the requirements of Headers.
*/ */
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
struct message struct message : message_headers<isRequest, Headers>
: std::conditional<isRequest,
detail::request_fields, detail::response_fields>::type
{ {
/// The container used to hold the request or response headers
using base_type = message_headers<isRequest, Headers>;
/** The type controlling the body traits. /** The type controlling the body traits.
The body member will be of type `body_type::value_type`. The body member will be of type `body_type::value_type`.
*/ */
using body_type = Body; 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<bool, isRequest>;
/// The container holding the headers.
headers_type headers;
/// A container representing the body. /// A container representing the body.
typename Body::value_type body; typename Body::value_type body;
/// Default constructor /// Default constructor
message() = default; message() = default;
/** Construct a message from headers.
Additional arguments, if any, are forwarded to
the constructor of the body member.
*/
template<class... Args>
explicit
message(base_type&& base, Args&&... args)
: base_type(std::move(base))
, body(std::forward<Args>(args)...)
{
}
/** Construct a message from headers.
Additional arguments, if any, are forwarded to
the constructor of the body member.
*/
template<class... Args>
explicit
message(base_type const& base, Args&&... args)
: base_type(base)
, body(std::forward<Args>(args)...)
{
}
/** Construct a message. /** Construct a message.
@param u An argument forwarded to the body constructor. @param u An argument forwarded to the body constructor.
*/ */
template<class U> template<class U,
class = typename std::enable_if<! std::is_same<
typename std::decay<U>::type, base_type>::value>>
explicit explicit
message(U&& u) message(U&& u)
: body(std::forward<U>(u)) : body(std::forward<U>(u))
@ -110,9 +262,11 @@ struct message
@param u An argument forwarded to the body constructor. @param u An argument forwarded to the body constructor.
@param v An argument forwarded to the headers constructor. @param v An argument forwarded to the headers constructor.
*/ */
template<class U, class V> template<class U, class V,
class = typename std::enable_if<! std::is_same<
typename std::decay<U>::type, base_type>::value>>
message(U&& u, V&& v) message(U&& u, V&& v)
: headers(std::forward<V>(v)) : base_type(std::forward<V>(v))
, body(std::forward<U>(u)) , body(std::forward<U>(u))
{ {
} }
@ -126,7 +280,6 @@ struct message
: message(std::piecewise_construct, un, : message(std::piecewise_construct, un,
beast::detail::make_index_sequence<sizeof...(Un)>{}) beast::detail::make_index_sequence<sizeof...(Un)>{})
{ {
} }
/** Construct a message. /** Construct a message.
@ -143,14 +296,7 @@ struct message
{ {
} }
/// Swap this message for another message.
void
swap(message& other);
private: private:
using base = typename std::conditional<isRequest,
detail::request_fields, detail::response_fields>::type;
template<class... Un, size_t... IUn> template<class... Un, size_t... IUn>
message(std::piecewise_construct_t, message(std::piecewise_construct_t,
std::tuple<Un...>& tu, beast::detail::index_sequence<IUn...>) std::tuple<Un...>& tu, beast::detail::index_sequence<IUn...>)
@ -164,31 +310,25 @@ private:
std::tuple<Un...>& tu, std::tuple<Vn...>& tv, std::tuple<Un...>& tu, std::tuple<Vn...>& tv,
beast::detail::index_sequence<IUn...>, beast::detail::index_sequence<IUn...>,
beast::detail::index_sequence<IVn...>) beast::detail::index_sequence<IVn...>)
: headers(std::forward<Vn>(std::get<IVn>(tv))...) : base_type(std::forward<Vn>(std::get<IVn>(tv))...)
, body(std::forward<Un>(std::get<IUn>(tu))...) , body(std::forward<Un>(std::get<IUn>(tu))...)
{ {
} }
}; };
template<bool isRequest, class Body, class Headers>
void
message<isRequest, Body, Headers>::
swap(message& other)
{
using std::swap;
base::swap(other);
swap(headers, other.headers);
swap(body, other.body);
}
/// Swap one message for another message. /// Swap one message for another message.
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
inline
void void
swap(message<isRequest, Body, Headers>& lhs, swap(
message<isRequest, Body, Headers>& rhs) message<isRequest, Body, Headers>& a,
message<isRequest, Body, Headers>& b)
{ {
lhs.swap(rhs); using std::swap;
using base_type = typename message<
isRequest, Body, Headers>::base_type;
swap(static_cast<base_type&>(a),
static_cast<base_type&>(b));
swap(a.body, b.body);
} }
/// A typical HTTP request /// A typical HTTP request
@ -201,7 +341,58 @@ template<class Body,
class Headers = basic_headers<std::allocator<char>>> class Headers = basic_headers<std::allocator<char>>>
using response = message<false, Body, Headers>; using response = message<false, Body, Headers>;
/** Returns `true` if a HTTP/1 message indicates a keep alive.
Undefined behavior if version is greater than 11.
*/
template<bool isRequest, class Body, class Headers>
bool
is_keep_alive(message<isRequest, Body, Headers> 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 isRequest, class Body, class Headers>
bool
is_upgrade(message<isRequest, Body, Headers> 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<isRequest, Body, Headers>& msg,
Options&&... options);
} // http } // http
} // beast } // beast
#include <beast/http/impl/message.ipp>
#endif #endif

View File

@ -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 <beast/http/message.hpp>
#include <memory>
#include <string>
#include <type_traits>
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<bool isRequest, class Body, class Headers>
struct message_v1 : message<isRequest, Body, Headers>
{
/// HTTP/1 version (10 or 11)
int version;
/// Default constructor
message_v1() = default;
/// Constructor
template<class Arg1, class... Argn,
class = typename std::enable_if<
! std::is_convertible<message_v1,
typename std::decay<Arg1>::type>::value>::type>
explicit
message_v1(Arg1&& arg1, Argn&&... argn)
: message<isRequest, Body, Headers>(
std::forward<Arg1>(arg1),
std::forward<Argn>(argn)...)
{
}
/// Swap this message for another message.
void
swap(message_v1& other);
};
template<bool isRequest, class Body, class Headers>
void
message_v1<isRequest, Body, Headers>::
swap(message_v1& other)
{
using std::swap;
message<isRequest, Body, Headers>::swap(other);
swap(version, other.version);
}
/// Swap one message for another message.
template<bool isRequest, class Body, class Headers>
inline
void
swap(message_v1<isRequest, Body, Headers>& lhs,
message_v1<isRequest, Body, Headers>& rhs)
{
lhs.swap(rhs);
}
/// A typical HTTP/1 request
template<class Body,
class Headers = basic_headers<std::allocator<char>>>
using request_v1 = message_v1<true, Body, Headers>;
/// A typical HTTP/1 response
template<class Body,
class Headers = basic_headers<std::allocator<char>>>
using response_v1 = message_v1<false, Body, Headers>;
/// Returns `true` if a HTTP/1 message indicates a keep alive
template<bool isRequest, class Body, class Headers>
bool
is_keep_alive(message_v1<isRequest, Body, Headers> const& msg);
/// Returns `true` if a HTTP/1 message indicates an Upgrade request or response
template<bool isRequest, class Body, class Headers>
bool
is_upgrade(message_v1<isRequest, Body, Headers> 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<isRequest, Body, Headers>& msg,
Options&&... options);
} // http
} // beast
#include <beast/http/impl/message_v1.ipp>
#endif

View File

@ -10,7 +10,7 @@
#include <beast/http/basic_parser_v1.hpp> #include <beast/http/basic_parser_v1.hpp>
#include <beast/http/concepts.hpp> #include <beast/http/concepts.hpp>
#include <beast/http/message_v1.hpp> #include <beast/http/message.hpp>
#include <beast/core/error.hpp> #include <beast/core/error.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -71,7 +71,7 @@ struct skip_body
/** A parser for producing HTTP/1 messages. /** A parser for producing HTTP/1 messages.
This class uses the basic HTTP/1 wire format parser to convert 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. @note A new instance of the parser is required for each message.
*/ */
@ -85,7 +85,7 @@ class parser_v1
public: public:
/// The type of message this parser produces. /// The type of message this parser produces.
using message_type = using message_type =
message_v1<isRequest, Body, Headers>; message<isRequest, Body, Headers>;
private: private:
using reader = using reader =

View File

@ -10,7 +10,7 @@
#include <beast/core/async_completion.hpp> #include <beast/core/async_completion.hpp>
#include <beast/core/error.hpp> #include <beast/core/error.hpp>
#include <beast/http/message_v1.hpp> #include <beast/http/message.hpp>
namespace beast { namespace beast {
namespace http { namespace http {
@ -49,7 +49,7 @@ template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
read(SyncReadStream& stream, DynamicBuffer& dynabuf, read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg); message<isRequest, Body, Headers>& msg);
/** Read a HTTP/1 message from a stream. /** Read a HTTP/1 message from a stream.
@ -85,7 +85,7 @@ template<class SyncReadStream, class DynamicBuffer,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
read(SyncReadStream& stream, DynamicBuffer& dynabuf, read(SyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg, message<isRequest, Body, Headers>& msg,
error_code& ec); error_code& ec);
/** Start an asynchronous operation to read a HTTP/1 message from a stream. /** 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 ReadHandler, void(error_code)>::result_type
#endif #endif
async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf, async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
message_v1<isRequest, Body, Headers>& msg, message<isRequest, Body, Headers>& msg,
ReadHandler&& handler); ReadHandler&& handler);
} // http } // http

View File

@ -8,7 +8,7 @@
#ifndef BEAST_HTTP_WRITE_HPP #ifndef BEAST_HTTP_WRITE_HPP
#define BEAST_HTTP_WRITE_HPP #define BEAST_HTTP_WRITE_HPP
#include <beast/http/message_v1.hpp> #include <beast/http/message.hpp>
#include <beast/core/error.hpp> #include <beast/core/error.hpp>
#include <beast/core/async_completion.hpp> #include <beast/core/async_completion.hpp>
#include <ostream> #include <ostream>
@ -46,7 +46,7 @@ template<class SyncWriteStream,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
write(SyncWriteStream& stream, write(SyncWriteStream& stream,
message_v1<isRequest, Body, Headers> const& msg); message<isRequest, Body, Headers> const& msg);
/** Write a HTTP/1 message on a stream. /** Write a HTTP/1 message on a stream.
@ -77,7 +77,7 @@ template<class SyncWriteStream,
bool isRequest, class Body, class Headers> bool isRequest, class Body, class Headers>
void void
write(SyncWriteStream& stream, write(SyncWriteStream& stream,
message_v1<isRequest, Body, Headers> const& msg, message<isRequest, Body, Headers> const& msg,
error_code& ec); error_code& ec);
/** Start an asynchronous operation to write a HTTP/1 message to a stream. /** 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 WriteHandler, void(error_code)>::result_type
#endif #endif
async_write(AsyncWriteStream& stream, async_write(AsyncWriteStream& stream,
message_v1<isRequest, Body, Headers> const& msg, message<isRequest, Body, Headers> const& msg,
WriteHandler&& handler); WriteHandler&& handler);
/** Serialize a HTTP/1 message to an ostream. /** Serialize a HTTP/1 message to an ostream.
@ -150,7 +150,7 @@ async_write(AsyncWriteStream& stream,
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
std::ostream& std::ostream&
operator<<(std::ostream& os, operator<<(std::ostream& os,
message_v1<isRequest, Body, Headers> const& msg); message<isRequest, Body, Headers> const& msg);
} // http } // http
} // beast } // beast

View File

@ -9,7 +9,7 @@
#define BEAST_WEBSOCKET_IMPL_ACCEPT_OP_HPP #define BEAST_WEBSOCKET_IMPL_ACCEPT_OP_HPP
#include <beast/websocket/impl/response_op.ipp> #include <beast/websocket/impl/response_op.ipp>
#include <beast/http/message_v1.hpp> #include <beast/http/message.hpp>
#include <beast/http/parser_v1.hpp> #include <beast/http/parser_v1.hpp>
#include <beast/http/read.hpp> #include <beast/http/read.hpp>
#include <beast/core/handler_alloc.hpp> #include <beast/core/handler_alloc.hpp>
@ -33,7 +33,7 @@ class stream<NextLayer>::accept_op
struct data struct data
{ {
stream<NextLayer>& ws; stream<NextLayer>& ws;
http::request_v1<http::string_body> req; http::request<http::string_body> req;
Handler h; Handler h;
bool cont; bool cont;
int state = 0; int state = 0;

View File

@ -9,7 +9,7 @@
#define BEAST_WEBSOCKET_IMPL_HANDSHAKE_OP_HPP #define BEAST_WEBSOCKET_IMPL_HANDSHAKE_OP_HPP
#include <beast/http/empty_body.hpp> #include <beast/http/empty_body.hpp>
#include <beast/http/message_v1.hpp> #include <beast/http/message.hpp>
#include <beast/http/read.hpp> #include <beast/http/read.hpp>
#include <beast/http/write.hpp> #include <beast/http/write.hpp>
#include <beast/core/handler_alloc.hpp> #include <beast/core/handler_alloc.hpp>
@ -33,8 +33,8 @@ class stream<NextLayer>::handshake_op
stream<NextLayer>& ws; stream<NextLayer>& ws;
Handler h; Handler h;
std::string key; std::string key;
http::request_v1<http::empty_body> req; http::request<http::empty_body> req;
http::response_v1<http::string_body> resp; http::response<http::string_body> resp;
bool cont; bool cont;
int state = 0; int state = 0;

View File

@ -8,7 +8,7 @@
#ifndef BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP #ifndef BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP
#define BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP #define BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP
#include <beast/http/message_v1.hpp> #include <beast/http/message.hpp>
#include <beast/http/string_body.hpp> #include <beast/http/string_body.hpp>
#include <beast/http/write.hpp> #include <beast/http/write.hpp>
#include <beast/core/handler_alloc.hpp> #include <beast/core/handler_alloc.hpp>
@ -28,7 +28,7 @@ class stream<NextLayer>::response_op
struct data struct data
{ {
stream<NextLayer>& ws; stream<NextLayer>& ws;
http::response_v1<http::string_body> resp; http::response<http::string_body> resp;
Handler h; Handler h;
error_code final_ec; error_code final_ec;
bool cont; bool cont;
@ -37,7 +37,7 @@ class stream<NextLayer>::response_op
template<class DeducedHandler, template<class DeducedHandler,
class Body, class Headers> class Body, class Headers>
data(DeducedHandler&& h_, stream<NextLayer>& ws_, data(DeducedHandler&& h_, stream<NextLayer>& ws_,
http::request_v1<Body, Headers> const& req, http::request<Body, Headers> const& req,
bool cont_) bool cont_)
: ws(ws_) : ws(ws_)
, resp(ws_.build_response(req)) , resp(ws_.build_response(req))

View File

@ -116,7 +116,7 @@ accept(ConstBufferSequence const& buffers, error_code& ec)
stream_.buffer().commit(buffer_copy( stream_.buffer().commit(buffer_copy(
stream_.buffer().prepare( stream_.buffer().prepare(
buffer_size(buffers)), buffers)); buffer_size(buffers)), buffers));
http::request_v1<http::string_body> m; http::request<http::string_body> m;
http::read(next_layer(), stream_.buffer(), m, ec); http::read(next_layer(), stream_.buffer(), m, ec);
if(ec) if(ec)
return; return;
@ -147,7 +147,7 @@ template<class NextLayer>
template<class Body, class Headers> template<class Body, class Headers>
void void
stream<NextLayer>:: stream<NextLayer>::
accept(http::request_v1<Body, Headers> const& request) accept(http::request<Body, Headers> const& request)
{ {
static_assert(is_SyncStream<next_layer_type>::value, static_assert(is_SyncStream<next_layer_type>::value,
"SyncStream requirements not met"); "SyncStream requirements not met");
@ -161,7 +161,7 @@ template<class NextLayer>
template<class Body, class Headers> template<class Body, class Headers>
void void
stream<NextLayer>:: stream<NextLayer>::
accept(http::request_v1<Body, Headers> const& req, accept(http::request<Body, Headers> const& req,
error_code& ec) error_code& ec)
{ {
static_assert(is_SyncStream<next_layer_type>::value, static_assert(is_SyncStream<next_layer_type>::value,
@ -186,7 +186,7 @@ template<class Body, class Headers, class AcceptHandler>
typename async_completion< typename async_completion<
AcceptHandler, void(error_code)>::result_type AcceptHandler, void(error_code)>::result_type
stream<NextLayer>:: stream<NextLayer>::
async_accept(http::request_v1<Body, Headers> const& req, async_accept(http::request<Body, Headers> const& req,
AcceptHandler&& handler) AcceptHandler&& handler)
{ {
static_assert(is_AsyncStream<next_layer_type>::value, static_assert(is_AsyncStream<next_layer_type>::value,
@ -230,7 +230,7 @@ handshake(boost::string_ref const& host,
build_request(host, resource, key), ec); build_request(host, resource, key), ec);
if(ec) if(ec)
return; return;
http::response_v1<http::string_body> res; http::response<http::string_body> res;
http::read(next_layer(), stream_.buffer(), res, ec); http::read(next_layer(), stream_.buffer(), res, ec);
if(ec) if(ec)
return; return;
@ -839,12 +839,12 @@ reset()
} }
template<class NextLayer> template<class NextLayer>
http::request_v1<http::empty_body> http::request<http::empty_body>
stream<NextLayer>:: stream<NextLayer>::
build_request(boost::string_ref const& host, build_request(boost::string_ref const& host,
boost::string_ref const& resource, std::string& key) boost::string_ref const& resource, std::string& key)
{ {
http::request_v1<http::empty_body> req; http::request<http::empty_body> req;
req.url = { resource.data(), resource.size() }; req.url = { resource.data(), resource.size() };
req.version = 11; req.version = 11;
req.method = "GET"; req.method = "GET";
@ -860,14 +860,14 @@ build_request(boost::string_ref const& host,
template<class NextLayer> template<class NextLayer>
template<class Body, class Headers> template<class Body, class Headers>
http::response_v1<http::string_body> http::response<http::string_body>
stream<NextLayer>:: stream<NextLayer>::
build_response(http::request_v1<Body, Headers> const& req) build_response(http::request<Body, Headers> const& req)
{ {
auto err = auto err =
[&](std::string const& text) [&](std::string const& text)
{ {
http::response_v1<http::string_body> res; http::response<http::string_body> res;
res.status = 400; res.status = 400;
res.reason = http::reason_string(res.status); res.reason = http::reason_string(res.status);
res.version = req.version; res.version = req.version;
@ -898,7 +898,7 @@ build_response(http::request_v1<Body, Headers> const& req)
return err("Missing Sec-WebSocket-Version"); return err("Missing Sec-WebSocket-Version");
if(version != "13") if(version != "13")
{ {
http::response_v1<http::string_body> res; http::response<http::string_body> res;
res.status = 426; res.status = 426;
res.reason = http::reason_string(res.status); res.reason = http::reason_string(res.status);
res.version = req.version; res.version = req.version;
@ -910,7 +910,7 @@ build_response(http::request_v1<Body, Headers> const& req)
return res; return res;
} }
} }
http::response_v1<http::string_body> res; http::response<http::string_body> res;
res.status = 101; res.status = 101;
res.reason = http::reason_string(res.status); res.reason = http::reason_string(res.status);
res.version = req.version; res.version = req.version;
@ -931,7 +931,7 @@ template<class NextLayer>
template<class Body, class Headers> template<class Body, class Headers>
void void
stream<NextLayer>:: stream<NextLayer>::
do_response(http::response_v1<Body, Headers> const& res, do_response(http::response<Body, Headers> const& res,
boost::string_ref const& key, error_code& ec) boost::string_ref const& key, error_code& ec)
{ {
// VFALCO Review these error codes // VFALCO Review these error codes

View File

@ -10,7 +10,7 @@
#include <beast/websocket/option.hpp> #include <beast/websocket/option.hpp>
#include <beast/websocket/detail/stream_base.hpp> #include <beast/websocket/detail/stream_base.hpp>
#include <beast/http/message_v1.hpp> #include <beast/http/message.hpp>
#include <beast/http/string_body.hpp> #include <beast/http/string_body.hpp>
#include <beast/core/dynabuf_readstream.hpp> #include <beast/core/dynabuf_readstream.hpp>
#include <beast/core/async_completion.hpp> #include <beast/core/async_completion.hpp>
@ -586,7 +586,7 @@ public:
// VFALCO TODO This should also take a DynamicBuffer with any leftover bytes. // VFALCO TODO This should also take a DynamicBuffer with any leftover bytes.
template<class Body, class Headers> template<class Body, class Headers>
void void
accept(http::request_v1<Body, Headers> const& request); accept(http::request<Body, Headers> const& request);
/** Respond to a WebSocket HTTP Upgrade request /** Respond to a WebSocket HTTP Upgrade request
@ -618,7 +618,7 @@ public:
*/ */
template<class Body, class Headers> template<class Body, class Headers>
void void
accept(http::request_v1<Body, Headers> const& request, accept(http::request<Body, Headers> const& request,
error_code& ec); error_code& ec);
/** Start responding to a WebSocket HTTP Upgrade request. /** Start responding to a WebSocket HTTP Upgrade request.
@ -669,7 +669,7 @@ public:
typename async_completion< typename async_completion<
AcceptHandler, void(error_code)>::result_type AcceptHandler, void(error_code)>::result_type
#endif #endif
async_accept(http::request_v1<Body, Headers> const& request, async_accept(http::request<Body, Headers> const& request,
AcceptHandler&& handler); AcceptHandler&& handler);
/** Send a HTTP WebSocket Upgrade request and receive the response. /** Send a HTTP WebSocket Upgrade request and receive the response.
@ -1530,18 +1530,18 @@ private:
void void
reset(); reset();
http::request_v1<http::empty_body> http::request<http::empty_body>
build_request(boost::string_ref const& host, build_request(boost::string_ref const& host,
boost::string_ref const& resource, boost::string_ref const& resource,
std::string& key); std::string& key);
template<class Body, class Headers> template<class Body, class Headers>
http::response_v1<http::string_body> http::response<http::string_body>
build_response(http::request_v1<Body, Headers> const& req); build_response(http::request<Body, Headers> const& req);
template<class Body, class Headers> template<class Body, class Headers>
void void
do_response(http::response_v1<Body, Headers> const& resp, do_response(http::response<Body, Headers> const& resp,
boost::string_ref const& key, error_code& ec); boost::string_ref const& key, error_code& ec);
void void

View File

@ -49,7 +49,6 @@ unit-test http-tests :
http/empty_body.cpp http/empty_body.cpp
http/headers.cpp http/headers.cpp
http/message.cpp http/message.cpp
http/message_v1.cpp
http/parse.cpp http/parse.cpp
http/parse_error.cpp http/parse_error.cpp
http/parser_v1.cpp http/parser_v1.cpp

View File

@ -18,7 +18,6 @@ add_executable (http-tests
empty_body.cpp empty_body.cpp
headers.cpp headers.cpp
message.cpp message.cpp
message_v1.cpp
parse.cpp parse.cpp
parse_error.cpp parse_error.cpp
parser_v1.cpp parser_v1.cpp

View File

@ -8,6 +8,7 @@
// Test that header file is self-contained. // Test that header file is self-contained.
#include <beast/http/message.hpp> #include <beast/http/message.hpp>
#include <beast/http/empty_body.hpp>
#include <beast/http/headers.hpp> #include <beast/http/headers.hpp>
#include <beast/http/string_body.hpp> #include <beast/http/string_body.hpp>
#include <beast/unit_test/suite.hpp> #include <beast/unit_test/suite.hpp>
@ -69,7 +70,7 @@ public:
}; };
}; };
void testConstruction() void testMessage()
{ {
static_assert(std::is_constructible< static_assert(std::is_constructible<
message<true, default_body, headers>>::value, ""); message<true, default_body, headers>>::value, "");
@ -125,10 +126,8 @@ public:
BEAST_EXPECT(! h.exists("User-Agent")); BEAST_EXPECT(! h.exists("User-Agent"));
BEAST_EXPECT(m.headers["User-Agent"] == "test"); BEAST_EXPECT(m.headers["User-Agent"] == "test");
} }
}
void testSwap() // swap
{
message<true, string_body, headers> m1; message<true, string_body, headers> m1;
message<true, string_body, headers> m2; message<true, string_body, headers> m2;
m1.url = "u"; m1.url = "u";
@ -147,9 +146,144 @@ public:
BEAST_EXPECT(m2.headers.exists("h")); 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<headers>;
static_assert(std::is_copy_constructible<req_type>::value, "");
static_assert(std::is_move_constructible<req_type>::value, "");
static_assert(std::is_copy_assignable<req_type>::value, "");
static_assert(std::is_move_assignable<req_type>::value, "");
using res_type = response_headers<headers>;
static_assert(std::is_copy_constructible<res_type>::value, "");
static_assert(std::is_move_constructible<res_type>::value, "");
static_assert(std::is_copy_assignable<res_type>::value, "");
static_assert(std::is_move_assignable<res_type>::value, "");
}
{
MoveHeaders h;
request_headers<MoveHeaders> r{std::move(h)};
BEAST_EXPECT(h.moved_from);
BEAST_EXPECT(r.headers.moved_to);
request<string_body, MoveHeaders> m{std::move(r)};
BEAST_EXPECT(r.headers.moved_from);
BEAST_EXPECT(m.headers.moved_to);
}
}
void testFreeFunctions()
{
{
request<empty_body> 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<empty_body> 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<false, string_body, headers> m1;
message<false, string_body, headers> 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 void run() override
{ {
testConstruction(); testMessage();
testHeaders();
testFreeFunctions();
testPrepare();
testSwap(); testSwap();
} }
}; };
@ -158,4 +292,3 @@ BEAST_DEFINE_TESTSUITE(message,http,beast);
} // http } // http
} // beast } // beast

View File

@ -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 <beast/http/message_v1.hpp>
#include <beast/http/headers.hpp>
#include <beast/http/string_body.hpp>
#include <beast/unit_test/suite.hpp>
#include <beast/http/empty_body.hpp>
namespace beast {
namespace http {
class message_v1_test : public beast::unit_test::suite
{
public:
void testFreeFunctions()
{
{
request_v1<empty_body> 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<empty_body> 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<false, string_body, headers> m1;
message_v1<false, string_body, headers> 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

View File

@ -10,7 +10,7 @@
#include "nodejs-parser/http_parser.h" #include "nodejs-parser/http_parser.h"
#include <beast/http/message_v1.hpp> #include <beast/http/message.hpp>
#include <beast/http/rfc7230.hpp> #include <beast/http/rfc7230.hpp>
#include <beast/core/buffer_concepts.hpp> #include <beast/core/buffer_concepts.hpp>
#include <beast/core/error.hpp> #include <beast/core/error.hpp>
@ -741,7 +741,7 @@ class nodejs_parser
: public nodejs_basic_parser<nodejs_parser<isRequest, Body, Headers>> : public nodejs_basic_parser<nodejs_parser<isRequest, Body, Headers>>
{ {
using message_type = using message_type =
message_v1<isRequest, Body, Headers>; message<isRequest, Body, Headers>;
message_type m_; message_type m_;
typename message_type::body_type::reader r_; typename message_type::body_type::reader r_;

View File

@ -259,7 +259,7 @@ public:
"Content-Length: 0\r\n" "Content-Length: 0\r\n"
"\r\n" "\r\n"
); );
request_v1<streambuf_body> m; request<streambuf_body> m;
try try
{ {
streambuf sb; streambuf sb;
@ -281,7 +281,7 @@ public:
"Content-Length: 0\r\n" "Content-Length: 0\r\n"
"\r\n" "\r\n"
); );
request_v1<streambuf_body> m; request<streambuf_body> m;
error_code ec; error_code ec;
streambuf sb; streambuf sb;
read(fs, sb, m, ec); read(fs, sb, m, ec);
@ -299,7 +299,7 @@ public:
"Content-Length: 0\r\n" "Content-Length: 0\r\n"
"\r\n" "\r\n"
); );
request_v1<streambuf_body> m; request<streambuf_body> m;
error_code ec; error_code ec;
streambuf sb; streambuf sb;
async_read(fs, sb, m, do_yield[ec]); async_read(fs, sb, m, do_yield[ec]);

View File

@ -222,7 +222,7 @@ public:
template<bool isRequest, class Body, class Headers> template<bool isRequest, class Body, class Headers>
std::string std::string
str(message_v1<isRequest, Body, Headers> const& m) str(message<isRequest, Body, Headers> const& m)
{ {
string_write_stream ss(ios_); string_write_stream ss(ios_);
write(ss, m); write(ss, m);
@ -233,7 +233,7 @@ public:
testAsyncWrite(yield_context do_yield) testAsyncWrite(yield_context do_yield)
{ {
{ {
message_v1<false, string_body, headers> m; message<false, string_body, headers> m;
m.version = 10; m.version = 10;
m.status = 200; m.status = 200;
m.reason = "OK"; m.reason = "OK";
@ -252,7 +252,7 @@ public:
"*****"); "*****");
} }
{ {
message_v1<false, string_body, headers> m; message<false, string_body, headers> m;
m.version = 11; m.version = 11;
m.status = 200; m.status = 200;
m.reason = "OK"; m.reason = "OK";
@ -285,7 +285,7 @@ public:
test::fail_counter fc(n); test::fail_counter fc(n);
test::fail_stream< test::fail_stream<
string_write_stream> fs(fc, ios_); string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m( message<true, fail_body, headers> m(
std::piecewise_construct, std::piecewise_construct,
std::forward_as_tuple(fc, ios_)); std::forward_as_tuple(fc, ios_));
m.method = "GET"; m.method = "GET";
@ -318,7 +318,7 @@ public:
test::fail_counter fc(n); test::fail_counter fc(n);
test::fail_stream< test::fail_stream<
string_write_stream> fs(fc, ios_); string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m( message<true, fail_body, headers> m(
std::piecewise_construct, std::piecewise_construct,
std::forward_as_tuple(fc, ios_)); std::forward_as_tuple(fc, ios_));
m.method = "GET"; m.method = "GET";
@ -353,7 +353,7 @@ public:
test::fail_counter fc(n); test::fail_counter fc(n);
test::fail_stream< test::fail_stream<
string_write_stream> fs(fc, ios_); string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m( message<true, fail_body, headers> m(
std::piecewise_construct, std::piecewise_construct,
std::forward_as_tuple(fc, ios_)); std::forward_as_tuple(fc, ios_));
m.method = "GET"; m.method = "GET";
@ -388,7 +388,7 @@ public:
test::fail_counter fc(n); test::fail_counter fc(n);
test::fail_stream< test::fail_stream<
string_write_stream> fs(fc, ios_); string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m( message<true, fail_body, headers> m(
std::piecewise_construct, std::piecewise_construct,
std::forward_as_tuple(fc, ios_)); std::forward_as_tuple(fc, ios_));
m.method = "GET"; m.method = "GET";
@ -418,7 +418,7 @@ public:
test::fail_counter fc(n); test::fail_counter fc(n);
test::fail_stream< test::fail_stream<
string_write_stream> fs(fc, ios_); string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m( message<true, fail_body, headers> m(
std::piecewise_construct, std::piecewise_construct,
std::forward_as_tuple(fc, ios_)); std::forward_as_tuple(fc, ios_));
m.method = "GET"; m.method = "GET";
@ -449,7 +449,7 @@ public:
{ {
// auto content-length HTTP/1.0 // auto content-length HTTP/1.0
{ {
message_v1<true, string_body, headers> m; message<true, string_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 10; m.version = 10;
@ -466,7 +466,7 @@ public:
} }
// keep-alive HTTP/1.0 // keep-alive HTTP/1.0
{ {
message_v1<true, string_body, headers> m; message<true, string_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 10; m.version = 10;
@ -484,7 +484,7 @@ public:
} }
// upgrade HTTP/1.0 // upgrade HTTP/1.0
{ {
message_v1<true, string_body, headers> m; message<true, string_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 10; m.version = 10;
@ -502,7 +502,7 @@ public:
} }
// no content-length HTTP/1.0 // no content-length HTTP/1.0
{ {
message_v1<true, unsized_body, headers> m; message<true, unsized_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 10; m.version = 10;
@ -522,7 +522,7 @@ public:
} }
// auto content-length HTTP/1.1 // auto content-length HTTP/1.1
{ {
message_v1<true, string_body, headers> m; message<true, string_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 11; m.version = 11;
@ -539,7 +539,7 @@ public:
} }
// close HTTP/1.1 // close HTTP/1.1
{ {
message_v1<true, string_body, headers> m; message<true, string_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 11; m.version = 11;
@ -561,7 +561,7 @@ public:
} }
// upgrade HTTP/1.1 // upgrade HTTP/1.1
{ {
message_v1<true, empty_body, headers> m; message<true, empty_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 11; m.version = 11;
@ -576,7 +576,7 @@ public:
} }
// no content-length HTTP/1.1 // no content-length HTTP/1.1
{ {
message_v1<true, unsized_body, headers> m; message<true, unsized_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 11; m.version = 11;
@ -600,7 +600,7 @@ public:
void testConvert() void testConvert()
{ {
message_v1<true, string_body, headers> m; message<true, string_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 11; m.version = 11;
@ -613,7 +613,7 @@ public:
void testOstream() void testOstream()
{ {
message_v1<true, string_body, headers> m; message<true, string_body, headers> m;
m.method = "GET"; m.method = "GET";
m.url = "/"; m.url = "/";
m.version = 11; m.version = 11;

View File

@ -184,7 +184,7 @@ public:
for(n = 0; n < limit; ++n) for(n = 0; n < limit; ++n)
{ {
// valid // valid
http::request_v1<http::empty_body> req; http::request<http::empty_body> req;
req.method = "GET"; req.method = "GET";
req.url = "/"; req.url = "/";
req.version = 11; req.version = 11;