Skip to content

Commit

Permalink
Refine message class hierarchy:
Browse files Browse the repository at this point in the history
Two new objects, request_headers and response_headers,
represent the portion of HTTP messages excluding the body.
  • Loading branch information
vinniefalco committed Oct 11, 2016
1 parent c2a420e commit 7906d71
Show file tree
Hide file tree
Showing 31 changed files with 566 additions and 476 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,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
Expand Down
80 changes: 39 additions & 41 deletions doc/http.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

[block '''
<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.body">Body</link></member>
<member><link linkend="beast.http.algorithms">Algorithms</link></member>
Expand Down Expand Up @@ -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 class templates are complete: they contain all the information needed
by the algorithms. Objects of this type 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<bool isRequest, class Body, class Headers>
template<
bool isRequest,
class Body,
class Headers
>
class message;

template<bool isRequest, class Body, class Headers>
class message_v1;
```

* [*`isRequest`]: Controls whether or not the message is a request or response.
Expand All @@ -76,38 +76,36 @@ These class templates have three template parameters:

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>;

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>;

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
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<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 url;
Headers headers;
typename Body::value_type body;
};

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;
std::string reason;
Headers headers;
Expand All @@ -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<string_body> req;
request<string_body> 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<string_body> res;
response<string_body> 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.";
```
Expand All @@ -147,7 +145,7 @@ The field names are not case-sensitive.
These statements change the values of the headers in the message passed:
```
template<class Body>
void set_fields(request_v1<Body>& req)
void set_fields(request<Body>& req)
{
if(! req.exists("User-Agent"))
req.insert("User-Agent", "myWebClient");
Expand Down Expand Up @@ -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<empty_body> req;
request<empty_body> req;
req.version = 11;
req.method = "GET";
req.url = "/index.html";
Expand All @@ -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<string_body> res;
response<string_body> res;
static_assert(std::is_same<decltype(res.body), std::string>::value);
res.body = "Here is the data you requested";
```
Expand Down Expand Up @@ -282,7 +280,7 @@ An asynchronous interface is available:
```
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));
```
Expand All @@ -297,7 +295,7 @@ stored in the streambuf parameter for use in a subsequent call to read:
```
boost::asio::streambuf sb;
...
response_v1<string_body> res;
response<string_body> res;
read(sock, sb, res); // Throws exception on error
...
// Alternatively
Expand All @@ -314,7 +312,7 @@ called:
void handle_read(boost::system::error_code);
...
boost::asio::streambuf sb;
response_v1<string_body> res;
response<string_body> res;
...
async_read(sock, res, std::bind(&handle_read, std::placeholders::_1));
```
Expand All @@ -326,7 +324,7 @@ is optimized for performance:
void handle_read(boost::system::error_code);
...
beast::streambuf sb;
response_v1<string_body> res;
response<string_body> res;
read(sock, sb, res);
```

Expand Down
9 changes: 8 additions & 1 deletion doc/quickref.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@
<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__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__streambuf_body">streambuf_body</link></member>
<member><link linkend="beast.ref.http__string_body">string_body</link></member>
Expand All @@ -60,6 +64,9 @@
<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_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__prepare">prepare</link></member>
<member><link linkend="beast.ref.http__read">read</link></member>
Expand Down
14 changes: 7 additions & 7 deletions examples/http_async_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<string_body>;
using resp_type = response_v1<file_body>;
using req_type = request<string_body>;
using resp_type = response<file_body>;

std::mutex m_;
bool log_ = true;
Expand Down Expand Up @@ -94,13 +94,13 @@ class http_async_server
struct data
{
Stream& s;
message_v1<isRequest, Body, Headers> m;
message<isRequest, Body, Headers> m;
Handler h;
bool cont;

template<class DeducedHandler>
data(DeducedHandler&& h_, Stream& s_,
message_v1<isRequest, Body, Headers>&& m_)
message<isRequest, Body, Headers>&& m_)
: s(s_)
, m(std::move(m_))
, h(std::forward<DeducedHandler>(h_))
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -236,7 +236,7 @@ class http_async_server
path = server_.root_ + path;
if(! boost::filesystem::exists(path))
{
response_v1<string_body> res;
response<string_body> res;
res.status = 404;
res.reason = "Not Found";
res.version = req_.version;
Expand Down Expand Up @@ -265,7 +265,7 @@ class http_async_server
}
catch(std::exception const& e)
{
response_v1<string_body> res;
response<string_body> res;
res.status = 500;
res.reason = "Internal Error";
res.version = req_.version;
Expand Down
4 changes: 2 additions & 2 deletions examples/http_crawl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ int main(int, char const*[])
ip::tcp::socket sock(ios);
connect(sock, it);
auto ep = sock.remote_endpoint();
request_v1<empty_body> req;
request<empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
Expand All @@ -44,7 +44,7 @@ int main(int, char const*[])
req.headers.insert("User-Agent", "beast/http");
prepare(req);
write(sock, req);
response_v1<string_body> res;
response<string_body> res;
streambuf sb;
beast::http::read(sock, sb, res);
std::cout << res;
Expand Down
4 changes: 2 additions & 2 deletions examples/http_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<beast::http::empty_body> req;
beast::http::request<beast::http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
Expand All @@ -32,7 +32,7 @@ int main()

// Receive and print HTTP response using beast
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);
std::cout << resp;
}
8 changes: 4 additions & 4 deletions examples/http_sync_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<string_body>;
using resp_type = response_v1<file_body>;
using req_type = request<string_body>;
using resp_type = response<file_body>;

bool log_ = true;
std::mutex m_;
Expand Down Expand Up @@ -161,7 +161,7 @@ class http_sync_server
path = root_ + path;
if(! boost::filesystem::exists(path))
{
response_v1<string_body> res;
response<string_body> res;
res.status = 404;
res.reason = "Not Found";
res.version = req.version;
Expand Down Expand Up @@ -190,7 +190,7 @@ class http_sync_server
}
catch(std::exception const& e)
{
response_v1<string_body> res;
response<string_body> res;
res.status = 500;
res.reason = "Internal Error";
res.version = req.version;
Expand Down
4 changes: 2 additions & 2 deletions examples/ssl/http_ssl_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ int main()
stream.handshake(ssl::stream_base::client);

// 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.url = "/";
req.version = 11;
Expand All @@ -45,7 +45,7 @@ int main()

// Receive and print HTTP response using Beast
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);
std::cout << resp;

Expand Down
1 change: 0 additions & 1 deletion include/beast/http.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include <beast/http/empty_body.hpp>
#include <beast/http/headers.hpp>
#include <beast/http/message.hpp>
#include <beast/http/message_v1.hpp>
#include <beast/http/parse.hpp>
#include <beast/http/parse_error.hpp>
#include <beast/http/parser_v1.hpp>
Expand Down
8 changes: 4 additions & 4 deletions include/beast/http/basic_headers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,14 @@ class basic_headers_base::const_iterator
@note Meets the requirements of @b `FieldSequence`.
*/
template<class Allocator>
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<Allocator>::
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<Allocator>::
Expand Down
Loading

0 comments on commit 7906d71

Please sign in to comment.