[/ 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) ] [section:http HTTP] Beast.HTTP offers programmers simple and performant models of HTTP messages and their associated operations including synchronous and asynchronous reading and writing using Boost.Asio. The HTTP protocol is described fully in [@https://tools.ietf.org/html/rfc2616 rfc2616] [section:motivation Motivation] The HTTP protocol is pervasive in network applications. As C++ is a logical choice for high performance network servers, there is great utility in solid building blocks for manipulating, sending, and receiving HTTP messages compliant with the Hypertext Transfer Protocol and the supplements that follow. Unfortunately reliable implementations or industry standards do not exist in C++. Beast.HTTP is built on Boost.Asio and uses HTTP parser from NodeJS, which is extensively field tested and exceptionally robust. A proposal to add networking functionality to the C++ standard library, based on Boost.Asio, is under consideration by the standards committee. Since the final approved networking interface for the C++ standard library will likely closely resemble the current interface of Boost.Asio, it is logical for Beast.HTTP to use Boost.Asio as its network transport. [note The documentation which follows assumes familiarity with both Boost.Asio and the HTTP protocol specification described in [@https://tools.ietf.org/html/rfc2616 rfc2616] ] [endsect] [section:example Example] All examples and identifiers mentioned in this document are written as if the following declarations are in effect: ``` #include using namespace beast::http; using namespace boost::asio; ``` Create a HTTP request: ``` request req({method_t::http_get, "/", 11}); req.headers.insert("Host", "127.0.0.1:80"); req.headers.insert("User-Agent", "Beast.HTTP"); ``` To send a message it must first be prepared through a call to `prepare`. This customization point transforms the `message` into a `prepared_message`, filling in some standard HTTP behavior and allowing the Body associated with the message to perform preparatory steps. For example, a string body may set the Content-Length and Content-Type appropriately. ``` void send_request(ip::tcp::socket& sock, request&& req) { // Send the request on the socket write(sock, prepare(req, connection(keep_alive)); } ``` Messages can be read from the network and parsed into a `parsed_message` object, which extends the `message` by adding parse-specific metadata such as the keep-alive which is context sensitive (depending on the HTTP version for example). When preparing a response for sending, `prepare` must be called with an additional parameter, the corresponding parsed request. The implementation inspects the contents of the request to set dependent fields of the response. This example reads a message, builds a response, and sends it. ``` void handle_connection(ip::tcp::socket& sock) { parsed_request req; read(sock, req); response resp; ... write(sock, prepare(resp, req)); } ``` [endsect] [section:message Message model] A HTTP message (referred to hereafter as "message") contains a request or response line, a series of zero or more name/value pairs (collectively termed "headers"), and a series of octets called the message body which may be zero in length. Applications using HTTP often perform these operations on messages: * [*Parse] a new message from a series of octets. * [*Assemble] a new message from scratch or from an existing message. * [*Serialize] a message into a series of octets. * [*Read] a message from a stream. This can be thought of as a compound operation; a network read, followed by a [*parse]. * [*Write] a message to a stream. This can be thought of as a compound operation: a [*serialize] followed by a network write. The spectrum of hardware and software platforms which perform these typical HTTP operations is vast, ranging from powerful servers in large datacenters to tiny resource-limited embedded devices. No single concrete implementation of a class intended to model messages can efficiently serve all needs. For example, an object that minimizes resources during parsing may not be able to edit and change headers dynamically. A message that represents the message body as a disk file may support sending but not parsing. Many efficient and correct models of messages exist, supporting some or all of the operations listed above. To support a variety of implementation strategies, we introduce customization points for the header and body via class template arguments. This illustration shows the message class template (boilerplate present in the actual declaration has been removed for clarity): [$images/message.png [width 580px] [height 225px]] The default constructor, move special members, and copy special members are all defaulted. A message is movable, copyable, or default constructible based on the capabilities of its template arguments. Messages modeled in this fashion are ['complete], containing all of the information required to perform the supported set of operations. They are ['first-class types], returnable from functions and composable. HTTP requests and responses are distinct types, allowing functions to be overloaded on the type of message. [endsect] [section:body Body parameter] The `Body` template argument in the `message` class must meet the [link beast.types.Body [*`Body`] requirements]. It provides customization of the data member in the message, the algorithm for parsing, and the algorithm for serialization: [$images/body.png [width 510px] [height 210px]] The following types, provided by the library, meet the `Body` requirements: * [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body. Used in GET requests where there is no message body. * [link beast.ref.http__string_body [*`string_body`:]] A body with a `value_type` of `std::string`. Useful for quickly putting together a request or response with simple text in the message body (such as an error message). Subject to the performance limit of strings if large amounts of data are inserted. * [link beast.ref.http__basic_streambuf_body [*`basic_streambuf_body`:]] A body with a `value_type` of `streambuf`. A streambuf is an efficient storage object which uses multiple octet arrays of varying lengths to represent data. Instances of the optional nested types `writer` and `reader` perform serialization and deserialization of the message body. If either or both of these types are present, the message becomes serializable, parsable, or both. They model [link beast.types.Reader [*`Reader`]] and [link beast.types.Writer [*`Writer`]] respectively. For specialized applications, users may implement their own types which meet the requirements. The examples included with this library provide a Body implementation used to serve files in a HTTP server. [endsect] [section:headers Headers container] The `Headers` type represents the field/value pairs present in every HTTP message. These types implement the [link beast.types.FieldSequence [*`FieldSequence`]] concept. The value type of a field sequence is an object meeting the requirements of [link beast.types.Field [*`Field`]]. The implementation can serialize any instance of `Headers` that meets the field sequence requirements. This example shows a function which returns `true` if the specified field sequence has a connect field: ``` template bool has_connect(FieldSequence const& fs) { return std::find_if(fs.begin(), fs.end(), [&](auto const& field) { return ci_equal(field.name(), "Connect"); }); } ``` [endsect] [endsect]