mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57:31 +02:00
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:
11
CHANGELOG.md
11
CHANGELOG.md
@ -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
|
||||||
|
80
doc/http.qbk
80
doc/http.qbk
@ -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);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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>::
|
||||||
|
@ -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 &&
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
@ -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 =
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
|
@ -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_;
|
||||||
|
@ -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]);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user