...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Beast provides a single class template message
and some aliases which model
HTTP/1 and HTTP/2
messages:
Table 1.15. Message
Name |
Description |
---|---|
/// An HTTP message template< bool isRequest, // `true` for requests, `false` for responses class Body, // Controls the container and algorithms used for the body class Fields = fields> // The type of container to store the fields class message; |
|
/// A typical HTTP request template<class Body, class Fields = fields> using request = message<true, Body, Fields>; |
|
/// A typical HTTP response template<class Body, class Fields = fields> using response = message<false, Body, Fields>; |
The container offers value semantics including move and copy if supported
by Body and
Fields.
User defined template function parameters can accept any message, or can
use partial specialization to accept just requests or responses. The default
fields
is a provided associative container using the standard allocator and supporting
modification and inspection of fields. As per rfc7230,
a non-case-sensitive comparison is used for field names. User defined types
for fields are possible. The Body
type determines the type of the container used to represent the body as well
as the algorithms for transferring buffers to and from the container. The
library comes with a collection of common body types. As with fields, user
defined body types are possible.
Sometimes it is desired to only work with a header. Beast provides a single
class template header
and some aliases to model
HTTP/1 and HTTP/2 headers:
Table 1.16. Header
Name |
Description |
---|---|
/// An HTTP header template< bool isRequest, // `true` for requests, `false` for responses class Fields = fields> // The type of container to store the fields class header; |
|
/// A typical HTTP request header template<class Fields> using request_header = header<true, Fields>; |
|
/// A typical HTTP response header template<class Fields> using response_header = header<false, Fields>; |
Requests and responses share the version, fields, and body but have a few
members unique to the type. This is implemented by declaring the header classes
as partial specializations of isRequest
.
message
is derived from header
; a message may be passed
as an argument to a function taking a suitably typed header as a parameter.
Additionally, header
is publicly
derived from Fields
; a message
inherits all the member functions of Fields
.
This diagram shows the inheritance relationship between header and message,
along with some of the notable differences in members in each partial specialization:
Beast defines the Body
concept, which determines both the type of the message::body
member (as seen in the diagram
above) and may also include algorithms for transferring buffers in and out.
These algorithms are used during parsing and serialization. Users may define
their own body types which meet the requirements, or use the ones that come
with the library:
Name |
Description |
---|---|
A body whose |
|
A body whose |
|
A special body with an empty |
|
This body is represented by a file opened for either reading or writing. Messages with this body may be serialized and parsed. HTTP algorithms will use the open file for reading and writing, for streaming and incremental sends and receives. |
|
A body whose |
|
A body whose |
|
A body whose |
These examples show how to create and fill in request and response objects: Here we build an HTTP GET request with an empty message body:
Table 1.17. Create Request
Statements |
Serialized Result |
---|---|
request<empty_body> req; req.version(11); // HTTP/1.1 req.method(verb::get); req.target("/index.htm"); req.set(field::accept, "text/html"); req.set(field::user_agent, "Beast"); |
GET /index.htm HTTP/1.1\r\n Accept: text/html\r\n User-Agent: Beast\r\n \r\n |
In this code we create an HTTP response with a status code indicating success.
This message has a body with a non-zero length. The function message::prepare_payload
automatically sets
the Content-Length or Transfer-Encoding field depending on the content and
type of the body
member.
Use of this function is optional; these fields may also be set explicitly.
Table 1.18. Create Response
Statements |
Serialized Result |
---|---|
response<string_body> res; res.version(11); // HTTP/1.1 res.result(status::ok); res.set(field::server, "Beast"); res.body() = "Hello, world!"; res.prepare_payload(); |
HTTP/1.1 200 OK\r\n Server: Beast\r\n Content-Length: 13\r\n \r\n Hello, world! |
The implementation will automatically fill in the obsolete reason-phrase
from the status code when serializing a message. Or it may be set directly
using header::reason
.