mirror of
https://github.com/boostorg/beast.git
synced 2025-08-03 14:54:32 +02:00
Refactor HTTP identifier names (API Change):
fix #171 Several names and HTTP identifiers are renamed to be more consistent, self-explanatory, and concise: * "Fields" is a collection of HTTP header fields (rfc7230 section 3.2) * "Header" is the Start Line plus Fields. Another way to look at it is, the HTTP message minus the body. * `basic_fields` replaces `basic_headers` * `fields` replaces `headers` * `Fields` replaces `Headers` in template parameter lists * `header` replaces `message_headers` * `header::fields` replaces `message_headers::fields` The changes are cosmetic and do not affect run-time behavior.
This commit is contained in:
@@ -1,3 +1,12 @@
|
||||
1.0.0-b20
|
||||
|
||||
API Changes:
|
||||
|
||||
* Rename HTTP identifiers
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
>>>>>>> b152207... .
|
||||
1.0.0-b19
|
||||
|
||||
* Boost library min/max guidance
|
||||
|
@@ -447,17 +447,16 @@ start. Other design goals:
|
||||
or frame data, which is of any type meeting the requirements of
|
||||
__DynamicBuffer__ (modeled after `boost::asio::streambuf`).
|
||||
|
||||
Beast comes with the class `beast::basic_streambuf`, an efficient
|
||||
implementation of the [*DynamicBuffer] concept which makes use of multiple
|
||||
Beast comes with the class __basic_streambuf__, an efficient
|
||||
implementation of the __DynamicBuffer__ concept which makes use of multiple
|
||||
allocated octet arrays. If an incoming message is broken up into
|
||||
multiple pieces, no reallocation occurs. Instead, new allocations are
|
||||
appended to the sequence when existing allocations are filled. Beast
|
||||
does not impose any particular memory management model on callers. The
|
||||
`basic_streambuf` provided by beast supports standard allocators through
|
||||
a template argument. Use the [*DynamicBuffer] that comes with beast,
|
||||
__basic_streambuf__ provided by beast supports standard allocators through
|
||||
a template argument. Use the __DynamicBuffer__ that comes with beast,
|
||||
customize the allocator if you desire, or provide your own type that
|
||||
meets the
|
||||
[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/basic_streambuf.hpp#L21 concept requirements].
|
||||
meets the requirements.
|
||||
|
||||
[table
|
||||
[
|
||||
|
280
doc/http.qbk
280
doc/http.qbk
@@ -5,30 +5,62 @@
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[/
|
||||
ideas:
|
||||
- complete send request walkthrough (client)
|
||||
- complete receive response walkthrough (client)
|
||||
- complete receive request walkthrough (server)
|
||||
- complete send response walkthrough (server)
|
||||
|
||||
- Introduce concepts from simple to complex
|
||||
- Smooth progression of new ideas building on the previous ideas
|
||||
|
||||
- do we show a simplified message with collapsed fields?
|
||||
- do we introduce `header` or `message` first?
|
||||
|
||||
|
||||
contents:
|
||||
Message (and header, fields)
|
||||
Create request
|
||||
Create response
|
||||
Algorithms
|
||||
Write
|
||||
Read
|
||||
Parse
|
||||
Examples
|
||||
Send Request
|
||||
Receive Response
|
||||
Receive Request
|
||||
Send Response
|
||||
Advanced
|
||||
Responding to HEAD
|
||||
Expect: 100-continue
|
||||
Body (user defined)
|
||||
|
||||
|
||||
section beast.http.examples Examples
|
||||
|
||||
note
|
||||
In the example code which follows, `socket` refers to an object of type
|
||||
`boost::asio::ip::tcp::socket` which is currently connected to a remote peer.
|
||||
]
|
||||
|
||||
|
||||
|
||||
[section:http Using HTTP]
|
||||
|
||||
[block '''
|
||||
<informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist>
|
||||
<member><link linkend="beast.http.message">Messages</link></member>
|
||||
<member><link linkend="beast.http.headers">Headers</link></member>
|
||||
<member><link linkend="beast.http.message">Message</link></member>
|
||||
<member><link linkend="beast.http.fields">Fields</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.sockets">Sockets</link></member>
|
||||
</simplelist></entry></row></tbody></tgroup></informaltable>
|
||||
''']
|
||||
|
||||
Beast.HTTP offers programmers simple and performant models of HTTP messages and
|
||||
Beast offers programmers simple and performant models of HTTP messages and
|
||||
their associated operations including synchronous and asynchronous reading and
|
||||
writing of messages in the HTTP/1 wire format using Boost.Asio.
|
||||
|
||||
A HTTP message (referred to hereafter as "message") contains request or
|
||||
response specific attributes, a series of zero or more name/value pairs
|
||||
(collectively termed "headers"), and a series of octets called the message
|
||||
body which may be zero in length. The HTTP protocol defines the client and
|
||||
server roles: clients send messages called requests and servers send back
|
||||
messages called responses.
|
||||
writing of messages and headers in the HTTP/1 wire format using Boost.Asio.
|
||||
|
||||
[note
|
||||
The following documentation assumes familiarity with both Boost.Asio
|
||||
@@ -36,6 +68,7 @@ messages called responses.
|
||||
and identifiers mentioned in this section are written as if the following
|
||||
declarations are in effect:
|
||||
```
|
||||
#include <beast/core.hpp>
|
||||
#include <beast/http.hpp>
|
||||
using namespace beast;
|
||||
using namespace beast::http;
|
||||
@@ -44,101 +77,124 @@ messages called responses.
|
||||
|
||||
|
||||
|
||||
[section:message Messages]
|
||||
|
||||
The __message__ class template models HTTP/1 and HTTP/2 requests and responses.
|
||||
These class templates are complete: they contain all the information needed
|
||||
by the algorithms. Objects of this type are first class: They may be returned
|
||||
from functions, moved, copied, passed as arguments, and stored in containers.
|
||||
Request and response messages are distinct types; functions may be overloaded
|
||||
on just one or the other if desired. Because this class template supports
|
||||
HTTP/1 and HTTP/2, it is sometimes referred to as the universal message model.
|
||||
|
||||
There are three important template parameters in the message class:
|
||||
[section:message Message]
|
||||
|
||||
The HTTP protocol defines the client and server roles: clients send messages
|
||||
called requests and servers send back messages called responses. A HTTP message
|
||||
(referred to hereafter as "message") contains request or response specific
|
||||
attributes (contained in the "Start Line"), a series of zero or more name/value
|
||||
pairs (collectively termed "Fields"), and an optional series of octets called
|
||||
the message body which may be zero in length. The start line for a HTTP request
|
||||
includes a string called the method, a string called the URL, and a version
|
||||
number indicating HTTP/1.0 or HTTP/1.1. For a response, the start line contains
|
||||
an integer status code and a string called the reason phrase. Alternatively, a
|
||||
HTTP message can be viewed as two parts: a header, followed by a body.
|
||||
|
||||
[note
|
||||
The Reason-Phrase is obsolete as of rfc7230.
|
||||
]
|
||||
|
||||
The __header__ class template models the header for HTTP/1 and HTTP/2 messages.
|
||||
This class template is a family of specializations, one for requests and one
|
||||
for responses, depending on the [*`isRequest`] template value.
|
||||
The [*`Fields`] template type determines the type of associative container
|
||||
used to store the field values. The provided __basic_fields__ class template
|
||||
and __fields__ type alias are typical choices for the [*`Fields`] type, but
|
||||
advanced applications may supply user defined types which meet the requirements.
|
||||
The __message__ class template models the header and optional body for HTTP/1
|
||||
and HTTP/2 requests and responses. It is derived from the __header__ class
|
||||
template with the same shared template parameters, and adds the `body` data
|
||||
member. The message class template requires an additional template argument
|
||||
type [*`Body`]. This type controls the container used to represent the body,
|
||||
if any, as well as the algorithms needed to serialize and parse bodies of
|
||||
that type.
|
||||
|
||||
This illustration shows the declarations and members of the __header__ and
|
||||
__message__ class templates, as well as the inheritance relationship:
|
||||
|
||||
[$images/message.png [width 650px] [height 390px]]
|
||||
|
||||
For notational convenience, these template type aliases are provided which
|
||||
supply typical choices for the [*`Fields`] type:
|
||||
```
|
||||
template<
|
||||
bool isRequest,
|
||||
class Body,
|
||||
class Headers
|
||||
>
|
||||
class message;
|
||||
using request_header = header<true, fields>;
|
||||
using response_header = header<false, fields>;
|
||||
|
||||
template<class Body, class Fields = fields>
|
||||
using request = message<true, Body, Fields>;
|
||||
|
||||
template<class Body, class Fields = fields>
|
||||
using response = message<false, Body, Fields>;
|
||||
```
|
||||
|
||||
* [*`isRequest`]: Controls whether or not the message is a request or response.
|
||||
Depending on the value, different data members will be present in the resulting
|
||||
type.
|
||||
The code examples below show how to create and fill in a request and response
|
||||
object:
|
||||
|
||||
* [*`Body`]: determines both the kind of container used to represent the
|
||||
message body and the algorithms used to parse and serialize it.
|
||||
|
||||
* [*`Headers`]: determines the container used to represent the HTTP headers.
|
||||
|
||||
For notational convenience, the following template type aliases are provided:
|
||||
```
|
||||
template<
|
||||
class Body,
|
||||
class Headers = basic_headers<std::allocator<char>>>
|
||||
using request = message<true, Body, Headers>;
|
||||
|
||||
template<
|
||||
class Body,
|
||||
class Headers = basic_headers<std::allocator<char>>>
|
||||
using response = message<false, Body, Headers>;
|
||||
```
|
||||
|
||||
The message class template has different data members depending on whether
|
||||
it represents a request or response. These simplified declarations
|
||||
notionally illustrate the members of HTTP/1 messages:
|
||||
|
||||
```
|
||||
template<class Body, class Headers>
|
||||
struct request
|
||||
{
|
||||
int version; // 10 for HTTP/1.0, 11 for HTTP/1.1
|
||||
std::string method;
|
||||
std::string url;
|
||||
Headers headers;
|
||||
typename Body::value_type body;
|
||||
};
|
||||
|
||||
template<class Body, class Headers>
|
||||
struct response
|
||||
{
|
||||
int version; // 10 for HTTP/1.0, 11 for HTTP/1.1
|
||||
int status;
|
||||
std::string reason;
|
||||
Headers headers;
|
||||
typename Body::value_type body;
|
||||
};
|
||||
```
|
||||
|
||||
These statements set fields in request and response message objects:
|
||||
```
|
||||
request<string_body> req;
|
||||
req.version = 11; // HTTP/1.1
|
||||
[table Create Message
|
||||
[[HTTP Request] [HTTP Response]]
|
||||
[[
|
||||
```
|
||||
request<empty_body> req;
|
||||
req.version = 11; // HTTP/1.1
|
||||
req.method = "GET";
|
||||
req.url = "/index.html";
|
||||
req.headers.insert("User-Agent", "Beast.HTTP");
|
||||
req.body = "";
|
||||
|
||||
req.url = "/index.htm"
|
||||
req.fields.insert("Accept", "text/html");
|
||||
req.fields.insert("Connection", "keep-alive");
|
||||
req.fields.insert("User-Agent", "Beast");
|
||||
```
|
||||
][
|
||||
```
|
||||
response<string_body> res;
|
||||
res.version = 10; // HTTP/1.0
|
||||
res.status = 404;
|
||||
res.reason = "Not Found";
|
||||
res.headers.insert("Server", "Beast.HTTP");
|
||||
res.body = "The requested resource was not found.";
|
||||
```
|
||||
res.version = 11; // HTTP/1.1
|
||||
res.status = 200;
|
||||
res.reason = "OK";
|
||||
res.fields.insert("Sever", "Beast");
|
||||
res.fields.insert("Content-Length", 4);
|
||||
res.body = "****";
|
||||
```
|
||||
]]]
|
||||
|
||||
In the serialized format of a HTTP message, the header is represented as a
|
||||
series of text lines ending in CRLF (`"\r\n"`). The end of the header is
|
||||
indicated by a line containing only CRLF. Here are examples of serialized HTTP
|
||||
request and response objects. The objects created above will produce these
|
||||
results when serialized. Note that only the response has a body:
|
||||
|
||||
[table Serialized HTTP Request and Response
|
||||
[[HTTP Request] [HTTP Response]]
|
||||
[[
|
||||
```
|
||||
GET /index.htm HTTP/1.1\r\n
|
||||
Accept: text/html\r\n
|
||||
Connection: keep-alive\r\n
|
||||
User-Agent: Beast\r\n
|
||||
\r\n
|
||||
```
|
||||
][
|
||||
```
|
||||
200 OK HTTP/1.1\r\n
|
||||
Server: Beast\r\n
|
||||
Content-Length: 4\r\n
|
||||
\r\n
|
||||
****
|
||||
```
|
||||
]]]
|
||||
|
||||
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:headers Headers]
|
||||
|
||||
The [*`Headers`] type represents a container that can set or retrieve the
|
||||
headers in a message. Beast provides the
|
||||
[link beast.ref.http__basic_headers `basic_headers`] class which serves
|
||||
[section:fields Fields]
|
||||
|
||||
The [*`Fields`] type represents a container that can set or retrieve the
|
||||
fields in a message. Beast provides the
|
||||
[link beast.ref.http__basic_fields `basic_fields`] class which serves
|
||||
the needs for most users. It supports modification and inspection of values.
|
||||
The field names are not case-sensitive.
|
||||
|
||||
@@ -157,15 +213,7 @@ These statements change the values of the headers in the message passed:
|
||||
}
|
||||
```
|
||||
|
||||
[heading Advanced]
|
||||
|
||||
This illustration shows more detail about the
|
||||
[link beast.ref.http__message [*`message`]] class template (boilerplate
|
||||
present in the actual declaration has been removed for clarity):
|
||||
|
||||
[$images/message.png [width 580px] [height 225px]]
|
||||
|
||||
User defined [*`Headers`] types are possible. To support serialization, the
|
||||
User defined [*`Fields`] types are possible. To support serialization, the
|
||||
type must meet the requirements of __FieldSequence__. To support parsing using
|
||||
the provided parser, the type must provide the `insert` member function.
|
||||
|
||||
@@ -233,30 +281,24 @@ serializing message bodies that come from a file.
|
||||
|
||||
[section:algorithms Algorithms]
|
||||
|
||||
In addition to the universal message model, Beast provides synchronous
|
||||
algorithms which operate on HTTP/1 messages:
|
||||
Algorithms are provided to serialize and deserialize HTTP/1 messages on
|
||||
streams.
|
||||
|
||||
* [link beast.ref.http__read [*read]]: Parse a message from a stream
|
||||
|
||||
* [link beast.ref.http__write [*write]]: Serialize a message into its wire format on a stream
|
||||
* [link beast.ref.http__read [*read]]: Deserialize a HTTP/1 __header__ or __message__ from a stream.
|
||||
* [link beast.ref.http__write [*write]]: Serialize a HTTP/1 __header__ or __message__ to a stream.
|
||||
|
||||
Asynchronous versions of these algorithms are also available:
|
||||
|
||||
* [link beast.ref.http__async_read [*async_read]]: Parse a message from a stream
|
||||
* [link beast.ref.http__async_read [*async_read]]: Deserialize a HTTP/1 __header__ or __message__ asynchronously from a stream.
|
||||
* [link beast.ref.http__async_write [*async_write]]: Serialize a HTTP/1 __header__ or __message__ asynchronously to a stream.
|
||||
|
||||
* [link beast.ref.http__async_write [*async_write]]: Serialize a message into its wire format on a stream
|
||||
[heading Using Sockets]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:sockets Using Sockets]
|
||||
|
||||
The library provides simple free functions modeled after Boost.Asio to
|
||||
send and receive messages on TCP/IP sockets, SSL streams, or any object
|
||||
which meets the Boost.Asio type requirements (SyncReadStream, SyncWriteStream,
|
||||
AsyncReadStream, and AsyncWriteStream depending on the types of operations
|
||||
performed). To send messages synchronously, use one of the
|
||||
The free function algorithms are modeled after Boost.Asio to send and receive
|
||||
messages on TCP/IP sockets, SSL streams, or any object which meets the
|
||||
Boost.Asio type requirements (__SyncReadStream__, __SyncWriteStream__,
|
||||
__AsyncReadStream__, and __AsyncWriteStream__ depending on the types of
|
||||
operations performed). To send messages synchronously, use one of the
|
||||
[link beast.ref.http__write `write`] functions:
|
||||
```
|
||||
void send_request(boost::asio::ip::tcp::socket& sock)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 30 KiB |
@@ -23,25 +23,33 @@
|
||||
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
|
||||
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
|
||||
|
||||
[def __asio_handler_invoke__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]]
|
||||
[def __asio_handler_allocate__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]]
|
||||
[def __AsyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]]
|
||||
[def __AsyncWriteStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]]
|
||||
[def __Body__ [link beast.ref.Body [*`Body`]]]
|
||||
[def __CompletionHandler__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]]
|
||||
[def __ConstBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]]
|
||||
[def __DynamicBuffer__ [link beast.ref.DynamicBuffer [*DynamicBuffer]]]
|
||||
[def __FieldSequence__ [link beast.ref.FieldSequence [*FieldSequence]]]
|
||||
[def __message__ [link beast.ref.http__message `message`]]
|
||||
[def __message_v1__ [link beast.ref.http__message_v1 `message_v1`]]
|
||||
[def __MutableBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]]
|
||||
[def __N4588__ [@http://cplusplus.github.io/networking-ts/draft.pdf [*N4588]]]
|
||||
[def __rfc6455__ [@https://tools.ietf.org/html/rfc6455 rfc6455]]
|
||||
[def __rfc7230__ [@https://tools.ietf.org/html/rfc7230 rfc7230]]
|
||||
[def __streambuf__ [link beast.ref.streambuf `streambuf`]]
|
||||
|
||||
[def __asio_handler_invoke__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]]
|
||||
[def __asio_handler_allocate__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]]
|
||||
[def __void_or_deduced__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]]
|
||||
|
||||
[def __AsyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]]
|
||||
[def __AsyncWriteStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]]
|
||||
[def __CompletionHandler__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]]
|
||||
[def __ConstBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]]
|
||||
[def __MutableBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]]
|
||||
[def __SyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]]
|
||||
[def __SyncWriteStream__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]]
|
||||
[def __void_or_deduced__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]]
|
||||
|
||||
[def __Body__ [link beast.ref.Body [*`Body`]]]
|
||||
[def __DynamicBuffer__ [link beast.ref.DynamicBuffer [*DynamicBuffer]]]
|
||||
[def __FieldSequence__ [link beast.ref.FieldSequence [*FieldSequence]]]
|
||||
[def __Parser__ [link beast.ref.Parser [*`Parser`]]]
|
||||
|
||||
[def __basic_fields__ [link beast.ref.http__basic_fields `basic_fields`]]
|
||||
[def __fields__ [link beast.ref.http__fields `fields`]]
|
||||
[def __header__ [link beast.ref.http__header `header`]]
|
||||
[def __message__ [link beast.ref.http__message `message`]]
|
||||
[def __streambuf__ [link beast.ref.streambuf `streambuf`]]
|
||||
[def __basic_streambuf__ [link beast.ref.basic_streambuf `basic_streambuf`]]
|
||||
|
||||
Beast is a cross-platform, header-only C++ library built on Boost.Asio that
|
||||
provides implementations of the HTTP and WebSocket protocols.
|
||||
|
@@ -30,24 +30,25 @@
|
||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.ref.http__basic_dynabuf_body">basic_dynabuf_body</link></member>
|
||||
<member><link linkend="beast.ref.http__basic_headers">basic_headers</link></member>
|
||||
<member><link linkend="beast.ref.http__basic_fields">basic_fields</link></member>
|
||||
<member><link linkend="beast.ref.http__basic_parser_v1">basic_parser_v1</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_parser_v1">headers_parser_v1</link></member>
|
||||
<member><link linkend="beast.ref.http__fields">fields</link></member>
|
||||
<member><link linkend="beast.ref.http__header">header</link></member>
|
||||
<member><link linkend="beast.ref.http__header_parser_v1">header_parser_v1</link></member>
|
||||
<member><link linkend="beast.ref.http__message">message</link></member>
|
||||
<member><link linkend="beast.ref.http__message_headers">message_headers</link></member>
|
||||
<member><link linkend="beast.ref.http__parser_v1">parser_v1</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__request_header">request_header</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__response_header">response_header</link></member>
|
||||
<member><link linkend="beast.ref.http__resume_context">resume_context</link></member>
|
||||
<member><link linkend="beast.ref.http__streambuf_body">streambuf_body</link></member>
|
||||
<member><link linkend="beast.ref.http__string_body">string_body</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">rfc7230</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
|
||||
<member><link linkend="beast.ref.http__ext_list">ext_list</link></member>
|
||||
<member><link linkend="beast.ref.http__param_list">param_list</link></member>
|
||||
<member><link linkend="beast.ref.http__token_list">token_list</link></member>
|
||||
@@ -56,20 +57,21 @@
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<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_parse">async_parse</link></member>
|
||||
<member><link linkend="beast.ref.http__async_write">async_write</link></member>
|
||||
<member><link linkend="beast.ref.http__chunk_encode">chunk_encode</link></member>
|
||||
<member><link linkend="beast.ref.http__chunk_encode_final">chunk_encode_final</link></member>
|
||||
<member><link linkend="beast.ref.http__swap">swap</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__operator_ls_">operator<<</link></member>
|
||||
<member><link linkend="beast.ref.http__parse">parse</link></member>
|
||||
<member><link linkend="beast.ref.http__prepare">prepare</link></member>
|
||||
<member><link linkend="beast.ref.http__read">read</link></member>
|
||||
<member><link linkend="beast.ref.http__swap">swap</link></member>
|
||||
<member><link linkend="beast.ref.http__reason_string">reason_string</link></member>
|
||||
<member><link linkend="beast.ref.http__with_body">with_body</link></member>
|
||||
<member><link linkend="beast.ref.http__write">write</link></member>
|
||||
<member><link linkend="beast.ref.http__operator_ls_">operator<<</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
@@ -84,14 +86,17 @@
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Options</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.ref.http__header_max_size">header_max_size</link></member>
|
||||
<member><link linkend="beast.ref.http__body_max_size">body_max_size</link></member>
|
||||
<member><link linkend="beast.ref.http__headers_max_size">headers_max_size</link></member>
|
||||
<member><link linkend="beast.ref.http__skip_body">skip_body</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Constants</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="beast.ref.http__body_what">body_what</link></member>
|
||||
<member><link linkend="beast.ref.http__connection">connection</link></member>
|
||||
<member><link linkend="beast.ref.http__no_content_length">no_content_length</link></member>
|
||||
<member><link linkend="beast.ref.http__parse_error">parse_error</link></member>
|
||||
<member><link linkend="beast.ref.http__parse_flag">parse_flag</link></member>
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
|
@@ -8,9 +8,12 @@
|
||||
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||
|
||||
#include <beast/http/body_type.hpp>
|
||||
#include <beast/core/error.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
@@ -34,8 +37,8 @@ struct file_body
|
||||
writer(writer const&) = delete;
|
||||
writer& operator=(writer const&) = delete;
|
||||
|
||||
template<bool isRequest, class Headers>
|
||||
writer(message<isRequest, file_body, Headers> const& m) noexcept
|
||||
template<bool isRequest, class Fields>
|
||||
writer(message<isRequest, file_body, Fields> const& m) noexcept
|
||||
: path_(m.body)
|
||||
{
|
||||
}
|
||||
|
@@ -85,7 +85,7 @@ public:
|
||||
|
||||
private:
|
||||
template<class Stream, class Handler,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
class write_op
|
||||
{
|
||||
using alloc_type =
|
||||
@@ -94,13 +94,13 @@ private:
|
||||
struct data
|
||||
{
|
||||
Stream& s;
|
||||
message<isRequest, Body, Headers> m;
|
||||
message<isRequest, Body, Fields> m;
|
||||
Handler h;
|
||||
bool cont;
|
||||
|
||||
template<class DeducedHandler>
|
||||
data(DeducedHandler&& h_, Stream& s_,
|
||||
message<isRequest, Body, Headers>&& m_)
|
||||
message<isRequest, Body, Fields>&& m_)
|
||||
: s(s_)
|
||||
, m(std::move(m_))
|
||||
, h(std::forward<DeducedHandler>(h_))
|
||||
@@ -170,16 +170,16 @@ private:
|
||||
};
|
||||
|
||||
template<class Stream,
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class DeducedHandler>
|
||||
static
|
||||
void
|
||||
async_write(Stream& stream, message<
|
||||
isRequest, Body, Headers>&& msg,
|
||||
isRequest, Body, Fields>&& msg,
|
||||
DeducedHandler&& handler)
|
||||
{
|
||||
write_op<Stream, typename std::decay<DeducedHandler>::type,
|
||||
isRequest, Body, Headers>{std::forward<DeducedHandler>(
|
||||
isRequest, Body, Fields>{std::forward<DeducedHandler>(
|
||||
handler), stream, std::move(msg)};
|
||||
}
|
||||
|
||||
@@ -240,8 +240,8 @@ private:
|
||||
res.status = 404;
|
||||
res.reason = "Not Found";
|
||||
res.version = req_.version;
|
||||
res.headers.insert("Server", "http_async_server");
|
||||
res.headers.insert("Content-Type", "text/html");
|
||||
res.fields.insert("Server", "http_async_server");
|
||||
res.fields.insert("Content-Type", "text/html");
|
||||
res.body = "The file '" + path + "' was not found";
|
||||
prepare(res);
|
||||
async_write(sock_, std::move(res),
|
||||
@@ -255,8 +255,8 @@ private:
|
||||
res.status = 200;
|
||||
res.reason = "OK";
|
||||
res.version = req_.version;
|
||||
res.headers.insert("Server", "http_async_server");
|
||||
res.headers.insert("Content-Type", mime_type(path));
|
||||
res.fields.insert("Server", "http_async_server");
|
||||
res.fields.insert("Content-Type", mime_type(path));
|
||||
res.body = path;
|
||||
prepare(res);
|
||||
async_write(sock_, std::move(res),
|
||||
@@ -269,8 +269,8 @@ private:
|
||||
res.status = 500;
|
||||
res.reason = "Internal Error";
|
||||
res.version = req_.version;
|
||||
res.headers.insert("Server", "http_async_server");
|
||||
res.headers.insert("Content-Type", "text/html");
|
||||
res.fields.insert("Server", "http_async_server");
|
||||
res.fields.insert("Content-Type", "text/html");
|
||||
res.body =
|
||||
std::string{"An internal error occurred"} + e.what();
|
||||
prepare(res);
|
||||
|
@@ -40,9 +40,9 @@ int main(int, char const*[])
|
||||
req.method = "GET";
|
||||
req.url = "/";
|
||||
req.version = 11;
|
||||
req.headers.insert("Host", host + std::string(":") +
|
||||
req.fields.insert("Host", host + std::string(":") +
|
||||
boost::lexical_cast<std::string>(ep.port()));
|
||||
req.headers.insert("User-Agent", "beast/http");
|
||||
req.fields.insert("User-Agent", "beast/http");
|
||||
prepare(req);
|
||||
write(sock, req);
|
||||
response<string_body> res;
|
||||
|
@@ -26,9 +26,9 @@ int main()
|
||||
req.method = "GET";
|
||||
req.url = "/";
|
||||
req.version = 11;
|
||||
req.headers.replace("Host", host + ":" +
|
||||
req.fields.replace("Host", host + ":" +
|
||||
boost::lexical_cast<std::string>(sock.remote_endpoint().port()));
|
||||
req.headers.replace("User-Agent", "Beast");
|
||||
req.fields.replace("User-Agent", "Beast");
|
||||
beast::http::prepare(req);
|
||||
beast::http::write(sock, req);
|
||||
|
||||
|
@@ -168,8 +168,8 @@ private:
|
||||
res.status = 404;
|
||||
res.reason = "Not Found";
|
||||
res.version = req.version;
|
||||
res.headers.insert("Server", "http_sync_server");
|
||||
res.headers.insert("Content-Type", "text/html");
|
||||
res.fields.insert("Server", "http_sync_server");
|
||||
res.fields.insert("Content-Type", "text/html");
|
||||
res.body = "The file '" + path + "' was not found";
|
||||
prepare(res);
|
||||
write(sock, res, ec);
|
||||
@@ -183,8 +183,8 @@ private:
|
||||
res.status = 200;
|
||||
res.reason = "OK";
|
||||
res.version = req.version;
|
||||
res.headers.insert("Server", "http_sync_server");
|
||||
res.headers.insert("Content-Type", mime_type(path));
|
||||
res.fields.insert("Server", "http_sync_server");
|
||||
res.fields.insert("Content-Type", mime_type(path));
|
||||
res.body = path;
|
||||
prepare(res);
|
||||
write(sock, res, ec);
|
||||
@@ -197,8 +197,8 @@ private:
|
||||
res.status = 500;
|
||||
res.reason = "Internal Error";
|
||||
res.version = req.version;
|
||||
res.headers.insert("Server", "http_sync_server");
|
||||
res.headers.insert("Content-Type", "text/html");
|
||||
res.fields.insert("Server", "http_sync_server");
|
||||
res.fields.insert("Content-Type", "text/html");
|
||||
res.body =
|
||||
std::string{"An internal error occurred: "} + e.what();
|
||||
prepare(res);
|
||||
|
@@ -38,9 +38,9 @@ int main()
|
||||
req.method = "GET";
|
||||
req.url = "/";
|
||||
req.version = 11;
|
||||
req.headers.insert("Host", host + ":" +
|
||||
req.fields.insert("Host", host + ":" +
|
||||
boost::lexical_cast<std::string>(sock.remote_endpoint().port()));
|
||||
req.headers.insert("User-Agent", "Beast");
|
||||
req.fields.insert("User-Agent", "Beast");
|
||||
beast::http::prepare(req);
|
||||
beast::http::write(stream, req);
|
||||
|
||||
|
@@ -46,7 +46,7 @@ namespace beast {
|
||||
|
||||
Example:
|
||||
@code
|
||||
// Process the next HTTP headers on the stream,
|
||||
// Process the next HTTP header on the stream,
|
||||
// leaving excess bytes behind for the next call.
|
||||
//
|
||||
template<class DynamicBuffer>
|
||||
@@ -54,7 +54,7 @@ namespace beast {
|
||||
dynabuf_readstream<DynamicBuffer>& stream)
|
||||
{
|
||||
// Read up to and including the end of the HTTP
|
||||
// headers, leaving the sequence in the stream's
|
||||
// header, leaving the sequence in the stream's
|
||||
// buffer. read_until may read past the end of the
|
||||
// headers; the return value will include only the
|
||||
// part up to the end of the delimiter.
|
||||
|
@@ -8,12 +8,11 @@
|
||||
#ifndef BEAST_HTTP_HPP
|
||||
#define BEAST_HTTP_HPP
|
||||
|
||||
#include <beast/http/basic_headers.hpp>
|
||||
#include <beast/http/basic_fields.hpp>
|
||||
#include <beast/http/basic_parser_v1.hpp>
|
||||
#include <beast/http/body_type.hpp>
|
||||
#include <beast/http/chunk_encode.hpp>
|
||||
#include <beast/http/empty_body.hpp>
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/fields.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/parse.hpp>
|
||||
#include <beast/http/parse_error.hpp>
|
||||
|
@@ -8,9 +8,12 @@
|
||||
#ifndef BEAST_HTTP_BASIC_DYNABUF_BODY_HPP
|
||||
#define BEAST_HTTP_BASIC_DYNABUF_BODY_HPP
|
||||
|
||||
#include <beast/http/body_type.hpp>
|
||||
#include <beast/core/error.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
@@ -34,10 +37,10 @@ private:
|
||||
value_type& sb_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
basic_dynabuf_body, Headers>& m) noexcept
|
||||
basic_dynabuf_body, Fields>& m) noexcept
|
||||
: sb_(m.body)
|
||||
{
|
||||
}
|
||||
@@ -63,10 +66,10 @@ private:
|
||||
DynamicBuffer const& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<
|
||||
isRequest, basic_dynabuf_body, Headers> const& m) noexcept
|
||||
isRequest, basic_dynabuf_body, Fields> const& m) noexcept
|
||||
: body_(m.body)
|
||||
{
|
||||
}
|
||||
|
@@ -5,11 +5,11 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_BASIC_HEADERS_HPP
|
||||
#define BEAST_HTTP_BASIC_HEADERS_HPP
|
||||
#ifndef BEAST_HTTP_BASIC_FIELDS_HPP
|
||||
#define BEAST_HTTP_BASIC_FIELDS_HPP
|
||||
|
||||
#include <beast/core/detail/empty_base_optimization.hpp>
|
||||
#include <beast/http/detail/basic_headers.hpp>
|
||||
#include <beast/http/detail/basic_fields.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
@@ -21,35 +21,35 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** A container for storing HTTP headers.
|
||||
/** A container for storing HTTP header fields.
|
||||
|
||||
This container is designed to store the field value pairs that make
|
||||
up the headers and trailers in a HTTP message. Objects of this type
|
||||
are iterable, which each element holding the field name and field
|
||||
up the fields and trailers in a HTTP message. Objects of this type
|
||||
are iterable, with each element holding the field name and field
|
||||
value.
|
||||
|
||||
Field names are stored as-is, but comparison are case-insensitive.
|
||||
Field names are stored as-is, but comparisons are case-insensitive.
|
||||
When the container is iterated, the fields are presented in the order
|
||||
of insertion. For fields with the same name, the container behaves
|
||||
as a std::multiset; there will be a separate value for each occurrence
|
||||
as a `std::multiset`; there will be a separate value for each occurrence
|
||||
of the field name.
|
||||
|
||||
@note Meets the requirements of @b `FieldSequence`.
|
||||
@note Meets the requirements of @b FieldSequence.
|
||||
*/
|
||||
template<class Allocator>
|
||||
class basic_headers :
|
||||
class basic_fields :
|
||||
#if ! GENERATING_DOCS
|
||||
private beast::detail::empty_base_optimization<
|
||||
typename std::allocator_traits<Allocator>::
|
||||
template rebind_alloc<
|
||||
detail::basic_headers_base::element>>,
|
||||
detail::basic_fields_base::element>>,
|
||||
#endif
|
||||
public detail::basic_headers_base
|
||||
public detail::basic_fields_base
|
||||
{
|
||||
using alloc_type = typename
|
||||
std::allocator_traits<Allocator>::
|
||||
template rebind_alloc<
|
||||
detail::basic_headers_base::element>;
|
||||
detail::basic_fields_base::element>;
|
||||
|
||||
using alloc_traits =
|
||||
std::allocator_traits<alloc_type>;
|
||||
@@ -61,16 +61,16 @@ class basic_headers :
|
||||
delete_all();
|
||||
|
||||
void
|
||||
move_assign(basic_headers&, std::false_type);
|
||||
move_assign(basic_fields&, std::false_type);
|
||||
|
||||
void
|
||||
move_assign(basic_headers&, std::true_type);
|
||||
move_assign(basic_fields&, std::true_type);
|
||||
|
||||
void
|
||||
copy_assign(basic_headers const&, std::false_type);
|
||||
copy_assign(basic_fields const&, std::false_type);
|
||||
|
||||
void
|
||||
copy_assign(basic_headers const&, std::true_type);
|
||||
copy_assign(basic_fields const&, std::true_type);
|
||||
|
||||
template<class FieldSequence>
|
||||
void
|
||||
@@ -103,17 +103,17 @@ public:
|
||||
#endif
|
||||
|
||||
/// Default constructor.
|
||||
basic_headers() = default;
|
||||
basic_fields() = default;
|
||||
|
||||
/// Destructor
|
||||
~basic_headers();
|
||||
~basic_fields();
|
||||
|
||||
/** Construct the headers.
|
||||
/** Construct the fields.
|
||||
|
||||
@param alloc The allocator to use.
|
||||
*/
|
||||
explicit
|
||||
basic_headers(Allocator const& alloc);
|
||||
basic_fields(Allocator const& alloc);
|
||||
|
||||
/** Move constructor.
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
|
||||
@param other The object to move from.
|
||||
*/
|
||||
basic_headers(basic_headers&& other);
|
||||
basic_fields(basic_fields&& other);
|
||||
|
||||
/** Move assignment.
|
||||
|
||||
@@ -129,25 +129,25 @@ public:
|
||||
|
||||
@param other The object to move from.
|
||||
*/
|
||||
basic_headers& operator=(basic_headers&& other);
|
||||
basic_fields& operator=(basic_fields&& other);
|
||||
|
||||
/// Copy constructor.
|
||||
basic_headers(basic_headers const&);
|
||||
basic_fields(basic_fields const&);
|
||||
|
||||
/// Copy assignment.
|
||||
basic_headers& operator=(basic_headers const&);
|
||||
basic_fields& operator=(basic_fields const&);
|
||||
|
||||
/// Copy constructor.
|
||||
template<class OtherAlloc>
|
||||
basic_headers(basic_headers<OtherAlloc> const&);
|
||||
basic_fields(basic_fields<OtherAlloc> const&);
|
||||
|
||||
/// Copy assignment.
|
||||
template<class OtherAlloc>
|
||||
basic_headers& operator=(basic_headers<OtherAlloc> const&);
|
||||
basic_fields& operator=(basic_fields<OtherAlloc> const&);
|
||||
|
||||
/// Construct from a field sequence.
|
||||
template<class FwdIt>
|
||||
basic_headers(FwdIt first, FwdIt last);
|
||||
basic_fields(FwdIt first, FwdIt last);
|
||||
|
||||
/// Returns `true` if the field sequence contains no elements.
|
||||
bool
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
boost::string_ref
|
||||
operator[](boost::string_ref const& name) const;
|
||||
|
||||
/// Clear the contents of the basic_headers.
|
||||
/// Clear the contents of the basic_fields.
|
||||
void
|
||||
clear() noexcept;
|
||||
|
||||
@@ -301,6 +301,6 @@ public:
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#include <beast/http/impl/basic_headers.ipp>
|
||||
#include <beast/http/impl/basic_fields.ipp>
|
||||
|
||||
#endif
|
@@ -22,8 +22,11 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
namespace parse_flag {
|
||||
enum values
|
||||
/** Parse flags
|
||||
|
||||
The set of parser bit flags are returned by @ref basic_parser_v1::flags.
|
||||
*/
|
||||
enum parse_flag
|
||||
{
|
||||
chunked = 1,
|
||||
connection_keep_alive = 2,
|
||||
@@ -34,28 +37,6 @@ enum values
|
||||
skipbody = 64,
|
||||
contentlength = 128
|
||||
};
|
||||
} // parse_flag
|
||||
|
||||
/** Headers maximum size option.
|
||||
|
||||
Sets the maximum number of cumulative bytes allowed
|
||||
including all header octets. A value of zero indicates
|
||||
no limit on the number of header octets
|
||||
|
||||
The default headers maximum size is 16KB (16,384 bytes).
|
||||
|
||||
@note Objects of this type are used with basic_parser_v1::set_option.
|
||||
*/
|
||||
struct headers_max_size
|
||||
{
|
||||
std::size_t value;
|
||||
|
||||
explicit
|
||||
headers_max_size(std::size_t v)
|
||||
: value(v)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** Body maximum size option.
|
||||
|
||||
@@ -67,7 +48,7 @@ struct headers_max_size
|
||||
The default body maximum size for requests is 4MB (four
|
||||
megabytes or 4,194,304 bytes) and unlimited for responses.
|
||||
|
||||
@note Objects of this type are used with basic_parser_v1::set_option.
|
||||
@note Objects of this type are used with @ref basic_parser_v1::set_option.
|
||||
*/
|
||||
struct body_max_size
|
||||
{
|
||||
@@ -80,9 +61,30 @@ struct body_max_size
|
||||
}
|
||||
};
|
||||
|
||||
/** Header maximum size option.
|
||||
|
||||
Sets the maximum number of cumulative bytes allowed
|
||||
including all header octets. A value of zero indicates
|
||||
no limit on the number of header octets.
|
||||
|
||||
The default header maximum size is 16KB (16,384 bytes).
|
||||
|
||||
@note Objects of this type are used with @ref basic_parser_v1::set_option.
|
||||
*/
|
||||
struct header_max_size
|
||||
{
|
||||
std::size_t value;
|
||||
|
||||
explicit
|
||||
header_max_size(std::size_t v)
|
||||
: value(v)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** A value indicating how the parser should treat the body.
|
||||
|
||||
This value is returned from the `on_headers` callback in
|
||||
This value is returned from the `on_header` callback in
|
||||
the derived class. It controls what the parser does next
|
||||
in terms of the message body.
|
||||
*/
|
||||
@@ -94,7 +96,7 @@ enum class body_what
|
||||
|
||||
/** Skip parsing of the body.
|
||||
|
||||
When returned by `on_headers` this causes parsing to
|
||||
When returned by `on_header` this causes parsing to
|
||||
complete and control to return to the caller. This
|
||||
could be used when sending a response to a HEAD
|
||||
request, for example.
|
||||
@@ -116,8 +118,8 @@ enum class body_what
|
||||
to the parser will begin reading the message body.
|
||||
|
||||
This could be used by callers to inspect the HTTP
|
||||
headers before committing to read the body. For example,
|
||||
to choose the body type based on the headers. Or to
|
||||
header before committing to read the body. For example,
|
||||
to choose the body type based on the fields. Or to
|
||||
respond to an Expect: 100-continue request.
|
||||
*/
|
||||
pause
|
||||
@@ -181,19 +183,19 @@ static std::uint64_t constexpr no_content_length =
|
||||
//
|
||||
void on_value(boost::string_ref const&, error_code&)
|
||||
|
||||
// Called when all the headers have been parsed successfully.
|
||||
// Called when the entire header has been parsed successfully.
|
||||
//
|
||||
void
|
||||
on_headers(std::uint64_t content_length, error_code&);
|
||||
on_header(std::uint64_t content_length, error_code&);
|
||||
|
||||
// Called after on_headers, before the body is parsed
|
||||
// Called after on_header, before the body is parsed
|
||||
//
|
||||
body_what
|
||||
on_body_what(std::uint64_t content_length, error_code&);
|
||||
|
||||
// Called for each piece of the body.
|
||||
//
|
||||
// If the headers indicate chunk encoding, the chunk
|
||||
// If the header indicates chunk encoding, the chunk
|
||||
// encoding is removed from the buffer before being
|
||||
// passed to the callback.
|
||||
//
|
||||
@@ -319,9 +321,9 @@ public:
|
||||
std::forward<An>(an)...);
|
||||
}
|
||||
|
||||
/// Set the headers maximum size option
|
||||
/// Set the header maximum size option
|
||||
void
|
||||
set_option(headers_max_size const& o)
|
||||
set_option(header_max_size const& o)
|
||||
{
|
||||
h_max_ = o.value;
|
||||
h_left_ = h_max_;
|
||||
@@ -508,7 +510,7 @@ private:
|
||||
void
|
||||
init(std::true_type)
|
||||
{
|
||||
// 16KB max headers, 4MB max body
|
||||
// Request: 16KB max header, 4MB max body
|
||||
h_max_ = 16 * 1024;
|
||||
b_max_ = 4 * 1024 * 1024;
|
||||
}
|
||||
@@ -516,7 +518,7 @@ private:
|
||||
void
|
||||
init(std::false_type)
|
||||
{
|
||||
// 16KB max headers, unlimited body
|
||||
// Response: 16KB max header, unlimited body
|
||||
h_max_ = 16 * 1024;
|
||||
b_max_ = 0;
|
||||
}
|
||||
@@ -616,7 +618,7 @@ private:
|
||||
|
||||
template<class T>
|
||||
struct check_on_headers<T, beast::detail::void_t<decltype(
|
||||
std::declval<T>().on_headers(
|
||||
std::declval<T>().on_header(
|
||||
std::declval<std::uint64_t>(),
|
||||
std::declval<error_code&>())
|
||||
)>> : std::true_type {};
|
||||
@@ -674,7 +676,7 @@ private:
|
||||
"on_method requirements not met");
|
||||
if(h_max_ && s.size() > h_left_)
|
||||
{
|
||||
ec = parse_error::headers_too_big;
|
||||
ec = parse_error::header_too_big;
|
||||
return;
|
||||
}
|
||||
h_left_ -= s.size();
|
||||
@@ -700,7 +702,7 @@ private:
|
||||
"on_uri requirements not met");
|
||||
if(h_max_ && s.size() > h_left_)
|
||||
{
|
||||
ec = parse_error::headers_too_big;
|
||||
ec = parse_error::header_too_big;
|
||||
return;
|
||||
}
|
||||
h_left_ -= s.size();
|
||||
@@ -726,7 +728,7 @@ private:
|
||||
"on_reason requirements not met");
|
||||
if(h_max_ && s.size() > h_left_)
|
||||
{
|
||||
ec = parse_error::headers_too_big;
|
||||
ec = parse_error::header_too_big;
|
||||
return;
|
||||
}
|
||||
h_left_ -= s.size();
|
||||
@@ -785,7 +787,7 @@ private:
|
||||
"on_field requirements not met");
|
||||
if(h_max_ && s.size() > h_left_)
|
||||
{
|
||||
ec = parse_error::headers_too_big;
|
||||
ec = parse_error::header_too_big;
|
||||
return;
|
||||
}
|
||||
h_left_ -= s.size();
|
||||
@@ -799,7 +801,7 @@ private:
|
||||
"on_value requirements not met");
|
||||
if(h_max_ && s.size() > h_left_)
|
||||
{
|
||||
ec = parse_error::headers_too_big;
|
||||
ec = parse_error::header_too_big;
|
||||
return;
|
||||
}
|
||||
h_left_ -= s.size();
|
||||
@@ -810,8 +812,8 @@ private:
|
||||
call_on_headers(error_code& ec)
|
||||
{
|
||||
static_assert(check_on_headers<Derived>::value,
|
||||
"on_headers requirements not met");
|
||||
impl().on_headers(content_length_, ec);
|
||||
"on_header requirements not met");
|
||||
impl().on_header(content_length_, ec);
|
||||
}
|
||||
|
||||
body_what
|
||||
|
@@ -1,19 +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_BODY_TYPE_HPP
|
||||
#define BEAST_HTTP_BODY_TYPE_HPP
|
||||
|
||||
// Convenience header to include everything
|
||||
// needed when declarating a user defined Body type.
|
||||
|
||||
#include <beast/core/error.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
|
||||
#endif
|
@@ -5,10 +5,11 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
|
||||
#define BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
|
||||
#ifndef BEAST_HTTP_CHUNK_ENCODE_HPP
|
||||
#define BEAST_HTTP_CHUNK_ENCODE_HPP
|
||||
|
||||
#include <beast/core/buffer_cat.hpp>
|
||||
#include <beast/http/detail/chunk_encode.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <algorithm>
|
||||
@@ -20,92 +21,6 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class chunk_encode_text
|
||||
{
|
||||
boost::asio::const_buffer cb_;
|
||||
|
||||
// Storage for the longest hex string we might need, plus delimiters.
|
||||
std::array<char, 2 * sizeof(std::size_t) + 2> buf_;
|
||||
|
||||
template<class = void>
|
||||
void
|
||||
copy(chunk_encode_text const& other);
|
||||
|
||||
template<class = void>
|
||||
void
|
||||
setup(std::size_t n);
|
||||
|
||||
template<class OutIter>
|
||||
static
|
||||
OutIter
|
||||
to_hex(OutIter last, std::size_t n)
|
||||
{
|
||||
if(n == 0)
|
||||
{
|
||||
*--last = '0';
|
||||
return last;
|
||||
}
|
||||
while(n)
|
||||
{
|
||||
*--last = "0123456789abcdef"[n&0xf];
|
||||
n>>=4;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
using const_iterator = value_type const*;
|
||||
|
||||
chunk_encode_text(chunk_encode_text const& other)
|
||||
{
|
||||
copy(other);
|
||||
}
|
||||
|
||||
explicit
|
||||
chunk_encode_text(std::size_t n)
|
||||
{
|
||||
setup(n);
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return &cb_;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return begin() + 1;
|
||||
}
|
||||
};
|
||||
template<class>
|
||||
void
|
||||
chunk_encode_text::
|
||||
copy(chunk_encode_text const& other)
|
||||
{
|
||||
auto const n =
|
||||
boost::asio::buffer_size(other.cb_);
|
||||
buf_ = other.buf_;
|
||||
cb_ = boost::asio::const_buffer(
|
||||
&buf_[buf_.size() - n], n);
|
||||
}
|
||||
|
||||
template<class>
|
||||
void
|
||||
chunk_encode_text::
|
||||
setup(std::size_t n)
|
||||
{
|
||||
buf_[buf_.size() - 2] = '\r';
|
||||
buf_[buf_.size() - 1] = '\n';
|
||||
auto it = to_hex(buf_.end() - 2, n);
|
||||
cb_ = boost::asio::const_buffer{&*it,
|
||||
static_cast<std::size_t>(
|
||||
std::distance(it, buf_.end()))};
|
||||
}
|
||||
|
||||
/** Returns a chunk-encoded ConstBufferSequence.
|
||||
|
||||
This returns a buffer sequence representing the
|
||||
@@ -124,7 +39,7 @@ template<class ConstBufferSequence>
|
||||
implementation_defined
|
||||
#else
|
||||
beast::detail::buffer_cat_helper<
|
||||
chunk_encode_text,
|
||||
detail::chunk_encode_delim,
|
||||
ConstBufferSequence,
|
||||
boost::asio::const_buffers_1>
|
||||
#endif
|
||||
@@ -132,7 +47,7 @@ chunk_encode(bool fin, ConstBufferSequence const& buffers)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
return buffer_cat(
|
||||
chunk_encode_text{buffer_size(buffers)},
|
||||
detail::chunk_encode_delim{buffer_size(buffers)},
|
||||
buffers,
|
||||
fin ? boost::asio::const_buffers_1{"\r\n0\r\n\r\n", 7}
|
||||
: boost::asio::const_buffers_1{"\r\n", 2});
|
||||
|
@@ -5,8 +5,8 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_DETAIL_BASIC_HEADERS_HPP
|
||||
#define BEAST_HTTP_DETAIL_BASIC_HEADERS_HPP
|
||||
#ifndef BEAST_HTTP_DETAIL_BASIC_FIELDS_HPP
|
||||
#define BEAST_HTTP_DETAIL_BASIC_FIELDS_HPP
|
||||
|
||||
#include <beast/core/detail/ci_char_traits.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
@@ -17,11 +17,11 @@ namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<class Allocator>
|
||||
class basic_headers;
|
||||
class basic_fields;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class basic_headers_base
|
||||
class basic_fields_base
|
||||
{
|
||||
public:
|
||||
struct value_type
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
|
||||
protected:
|
||||
template<class Allocator>
|
||||
friend class beast::http::basic_headers;
|
||||
friend class beast::http::basic_fields;
|
||||
|
||||
struct element
|
||||
: boost::intrusive::set_base_hook <
|
||||
@@ -105,7 +105,7 @@ protected:
|
||||
set_t set_;
|
||||
list_t list_;
|
||||
|
||||
basic_headers_base(set_t&& set, list_t&& list)
|
||||
basic_fields_base(set_t&& set, list_t&& list)
|
||||
: set_(std::move(set))
|
||||
, list_(std::move(list))
|
||||
{
|
||||
@@ -116,21 +116,21 @@ public:
|
||||
|
||||
using iterator = const_iterator;
|
||||
|
||||
basic_headers_base() = default;
|
||||
basic_fields_base() = default;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class basic_headers_base::const_iterator
|
||||
class basic_fields_base::const_iterator
|
||||
{
|
||||
using iter_type = list_t::const_iterator;
|
||||
|
||||
iter_type it_;
|
||||
|
||||
template<class Allocator>
|
||||
friend class beast::http::basic_headers;
|
||||
friend class beast::http::basic_fields;
|
||||
|
||||
friend class basic_headers_base;
|
||||
friend class basic_fields_base;
|
||||
|
||||
const_iterator(iter_type it)
|
||||
: it_(it)
|
||||
@@ -139,7 +139,7 @@ class basic_headers_base::const_iterator
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename basic_headers_base::value_type;
|
||||
typename basic_fields_base::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type const&;
|
||||
using difference_type = std::ptrdiff_t;
|
111
include/beast/http/detail/chunk_encode.hpp
Normal file
111
include/beast/http/detail/chunk_encode.hpp
Normal file
@@ -0,0 +1,111 @@
|
||||
//
|
||||
// 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_DETAIL_CHUNK_ENCODE_HPP
|
||||
#define BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
class chunk_encode_delim
|
||||
{
|
||||
boost::asio::const_buffer cb_;
|
||||
|
||||
// Storage for the longest hex string we might need, plus delimiters.
|
||||
std::array<char, 2 * sizeof(std::size_t) + 2> buf_;
|
||||
|
||||
template<class = void>
|
||||
void
|
||||
copy(chunk_encode_delim const& other);
|
||||
|
||||
template<class = void>
|
||||
void
|
||||
setup(std::size_t n);
|
||||
|
||||
template<class OutIter>
|
||||
static
|
||||
OutIter
|
||||
to_hex(OutIter last, std::size_t n)
|
||||
{
|
||||
if(n == 0)
|
||||
{
|
||||
*--last = '0';
|
||||
return last;
|
||||
}
|
||||
while(n)
|
||||
{
|
||||
*--last = "0123456789abcdef"[n&0xf];
|
||||
n>>=4;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
using const_iterator = value_type const*;
|
||||
|
||||
chunk_encode_delim(chunk_encode_delim const& other)
|
||||
{
|
||||
copy(other);
|
||||
}
|
||||
|
||||
explicit
|
||||
chunk_encode_delim(std::size_t n)
|
||||
{
|
||||
setup(n);
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return &cb_;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return begin() + 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<class>
|
||||
void
|
||||
chunk_encode_delim::
|
||||
copy(chunk_encode_delim const& other)
|
||||
{
|
||||
auto const n =
|
||||
boost::asio::buffer_size(other.cb_);
|
||||
buf_ = other.buf_;
|
||||
cb_ = boost::asio::const_buffer(
|
||||
&buf_[buf_.size() - n], n);
|
||||
}
|
||||
|
||||
template<class>
|
||||
void
|
||||
chunk_encode_delim::
|
||||
setup(std::size_t n)
|
||||
{
|
||||
buf_[buf_.size() - 2] = '\r';
|
||||
buf_[buf_.size() - 1] = '\n';
|
||||
auto it = to_hex(buf_.end() - 2, n);
|
||||
cb_ = boost::asio::const_buffer{&*it,
|
||||
static_cast<std::size_t>(
|
||||
std::distance(it, buf_.end()))};
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
@@ -8,9 +8,12 @@
|
||||
#ifndef BEAST_HTTP_EMPTY_BODY_HPP
|
||||
#define BEAST_HTTP_EMPTY_BODY_HPP
|
||||
|
||||
#include <beast/http/body_type.hpp>
|
||||
#include <beast/core/error.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -36,9 +39,9 @@ private:
|
||||
|
||||
struct writer
|
||||
{
|
||||
template<bool isRequest, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<isRequest, empty_body, Headers> const& m) noexcept
|
||||
writer(message<isRequest, empty_body, Fields> const& m) noexcept
|
||||
{
|
||||
beast::detail::ignore_unused(m);
|
||||
}
|
||||
|
@@ -5,17 +5,18 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_HEADERS_HPP
|
||||
#define BEAST_HTTP_HEADERS_HPP
|
||||
#ifndef BEAST_HTTP_FIELDS_HPP
|
||||
#define BEAST_HTTP_FIELDS_HPP
|
||||
|
||||
#include <beast/http/basic_headers.hpp>
|
||||
#include <beast/http/basic_fields.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
using headers =
|
||||
basic_headers<std::allocator<char>>;
|
||||
/// A typical HTTP header fields container
|
||||
using fields =
|
||||
basic_fields<std::allocator<char>>;
|
||||
|
||||
} // http
|
||||
} // beast
|
@@ -13,7 +13,6 @@
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/core/error.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@@ -36,100 +35,99 @@ struct response_parser_base
|
||||
|
||||
} // detail
|
||||
|
||||
/** A parser for HTTP/1 request and response headers.
|
||||
/** A parser for a HTTP/1 request or response header.
|
||||
|
||||
This class uses the HTTP/1 wire format parser to
|
||||
convert a series of octets into a @ref request_headers
|
||||
or @ref response_headers.
|
||||
convert a series of octets into a request or
|
||||
response @ref header.
|
||||
|
||||
@note A new instance of the parser is required for each message.
|
||||
*/
|
||||
template<bool isRequest, class Headers>
|
||||
class headers_parser_v1
|
||||
template<bool isRequest, class Fields>
|
||||
class header_parser_v1
|
||||
: public basic_parser_v1<isRequest,
|
||||
headers_parser_v1<isRequest, Headers>>
|
||||
header_parser_v1<isRequest, Fields>>
|
||||
, private std::conditional<isRequest,
|
||||
detail::request_parser_base,
|
||||
detail::response_parser_base>::type
|
||||
{
|
||||
public:
|
||||
/// The type of message this parser produces.
|
||||
using headers_type =
|
||||
message_headers<isRequest, Headers>;
|
||||
/// The type of the header this parser produces.
|
||||
using header_type = header<isRequest, Fields>;
|
||||
|
||||
private:
|
||||
// VFALCO Check Headers requirements?
|
||||
// VFALCO Check Fields requirements?
|
||||
|
||||
std::string field_;
|
||||
std::string value_;
|
||||
headers_type h_;
|
||||
header_type h_;
|
||||
bool flush_ = false;
|
||||
|
||||
public:
|
||||
/// Default constructor
|
||||
headers_parser_v1() = default;
|
||||
header_parser_v1() = default;
|
||||
|
||||
/// Move constructor
|
||||
headers_parser_v1(headers_parser_v1&&) = default;
|
||||
header_parser_v1(header_parser_v1&&) = default;
|
||||
|
||||
/// Copy constructor (disallowed)
|
||||
headers_parser_v1(headers_parser_v1 const&) = delete;
|
||||
header_parser_v1(header_parser_v1 const&) = delete;
|
||||
|
||||
/// Move assignment (disallowed)
|
||||
headers_parser_v1& operator=(headers_parser_v1&&) = delete;
|
||||
header_parser_v1& operator=(header_parser_v1&&) = delete;
|
||||
|
||||
/// Copy assignment (disallowed)
|
||||
headers_parser_v1& operator=(headers_parser_v1 const&) = delete;
|
||||
header_parser_v1& operator=(header_parser_v1 const&) = delete;
|
||||
|
||||
/** Construct the parser.
|
||||
|
||||
@param args Forwarded to the message headers constructor.
|
||||
@param args Forwarded to the header constructor.
|
||||
*/
|
||||
#if GENERATING_DOCS
|
||||
template<class... Args>
|
||||
explicit
|
||||
headers_parser_v1(Args&&... args);
|
||||
header_parser_v1(Args&&... args);
|
||||
#else
|
||||
template<class Arg1, class... ArgN,
|
||||
class = typename std::enable_if<! std::is_same<
|
||||
typename std::decay<Arg1>::type, headers_parser_v1>::value>>
|
||||
typename std::decay<Arg1>::type, header_parser_v1>::value>>
|
||||
explicit
|
||||
headers_parser_v1(Arg1&& arg1, ArgN&&... argn)
|
||||
header_parser_v1(Arg1&& arg1, ArgN&&... argn)
|
||||
: h_(std::forward<Arg1>(arg1),
|
||||
std::forward<ArgN>(argn)...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Returns the parsed headers.
|
||||
/** Returns the parsed header
|
||||
|
||||
Only valid if @ref complete would return `true`.
|
||||
*/
|
||||
headers_type const&
|
||||
header_type const&
|
||||
get() const
|
||||
{
|
||||
return h_;
|
||||
}
|
||||
|
||||
/** Returns the parsed headers.
|
||||
/** Returns the parsed header.
|
||||
|
||||
Only valid if @ref complete would return `true`.
|
||||
*/
|
||||
headers_type&
|
||||
header_type&
|
||||
get()
|
||||
{
|
||||
return h_;
|
||||
}
|
||||
|
||||
/** Returns ownership of the parsed headers.
|
||||
/** Returns ownership of the parsed header.
|
||||
|
||||
Ownership is transferred to the caller. Only
|
||||
valid if @ref complete would return `true`.
|
||||
|
||||
Requires:
|
||||
`message_headers<isRequest, Headers>` is @b MoveConstructible
|
||||
@ref header_type is @b MoveConstructible
|
||||
*/
|
||||
headers_type
|
||||
header_type
|
||||
release()
|
||||
{
|
||||
static_assert(std::is_move_constructible<decltype(h_)>::value,
|
||||
@@ -138,7 +136,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
friend class basic_parser_v1<isRequest, headers_parser_v1>;
|
||||
friend class basic_parser_v1<isRequest, header_parser_v1>;
|
||||
|
||||
void flush()
|
||||
{
|
||||
@@ -146,7 +144,7 @@ private:
|
||||
return;
|
||||
flush_ = false;
|
||||
BOOST_ASSERT(! field_.empty());
|
||||
h_.headers.insert(field_, value_);
|
||||
h_.fields.insert(field_, value_);
|
||||
field_.clear();
|
||||
value_.clear();
|
||||
}
|
||||
@@ -207,7 +205,7 @@ private:
|
||||
}
|
||||
|
||||
void
|
||||
on_headers(std::uint64_t, error_code&)
|
||||
on_header(std::uint64_t, error_code&)
|
||||
{
|
||||
flush();
|
||||
h_.version = 10 * this->http_major() + this->http_minor();
|
@@ -5,8 +5,8 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_FIELDS_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_FIELDS_IPP
|
||||
|
||||
#include <beast/http/detail/rfc7230.hpp>
|
||||
#include <algorithm>
|
||||
@@ -16,7 +16,7 @@ namespace http {
|
||||
|
||||
template<class Allocator>
|
||||
void
|
||||
basic_headers<Allocator>::
|
||||
basic_fields<Allocator>::
|
||||
delete_all()
|
||||
{
|
||||
for(auto it = list_.begin(); it != list_.end();)
|
||||
@@ -31,8 +31,8 @@ delete_all()
|
||||
template<class Allocator>
|
||||
inline
|
||||
void
|
||||
basic_headers<Allocator>::
|
||||
move_assign(basic_headers& other, std::false_type)
|
||||
basic_fields<Allocator>::
|
||||
move_assign(basic_fields& other, std::false_type)
|
||||
{
|
||||
if(this->member() != other.member())
|
||||
{
|
||||
@@ -49,8 +49,8 @@ move_assign(basic_headers& other, std::false_type)
|
||||
template<class Allocator>
|
||||
inline
|
||||
void
|
||||
basic_headers<Allocator>::
|
||||
move_assign(basic_headers& other, std::true_type)
|
||||
basic_fields<Allocator>::
|
||||
move_assign(basic_fields& other, std::true_type)
|
||||
{
|
||||
this->member() = std::move(other.member());
|
||||
set_ = std::move(other.set_);
|
||||
@@ -60,8 +60,8 @@ move_assign(basic_headers& other, std::true_type)
|
||||
template<class Allocator>
|
||||
inline
|
||||
void
|
||||
basic_headers<Allocator>::
|
||||
copy_assign(basic_headers const& other, std::false_type)
|
||||
basic_fields<Allocator>::
|
||||
copy_assign(basic_fields const& other, std::false_type)
|
||||
{
|
||||
copy_from(other);
|
||||
}
|
||||
@@ -69,8 +69,8 @@ copy_assign(basic_headers const& other, std::false_type)
|
||||
template<class Allocator>
|
||||
inline
|
||||
void
|
||||
basic_headers<Allocator>::
|
||||
copy_assign(basic_headers const& other, std::true_type)
|
||||
basic_fields<Allocator>::
|
||||
copy_assign(basic_fields const& other, std::true_type)
|
||||
{
|
||||
this->member() = other.member();
|
||||
copy_from(other);
|
||||
@@ -79,35 +79,35 @@ copy_assign(basic_headers const& other, std::true_type)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Allocator>
|
||||
basic_headers<Allocator>::
|
||||
~basic_headers()
|
||||
basic_fields<Allocator>::
|
||||
~basic_fields()
|
||||
{
|
||||
delete_all();
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
basic_headers<Allocator>::
|
||||
basic_headers(Allocator const& alloc)
|
||||
basic_fields<Allocator>::
|
||||
basic_fields(Allocator const& alloc)
|
||||
: beast::detail::empty_base_optimization<
|
||||
alloc_type>(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
basic_headers<Allocator>::
|
||||
basic_headers(basic_headers&& other)
|
||||
basic_fields<Allocator>::
|
||||
basic_fields(basic_fields&& other)
|
||||
: beast::detail::empty_base_optimization<alloc_type>(
|
||||
std::move(other.member()))
|
||||
, detail::basic_headers_base(
|
||||
, detail::basic_fields_base(
|
||||
std::move(other.set_), std::move(other.list_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
auto
|
||||
basic_headers<Allocator>::
|
||||
operator=(basic_headers&& other) ->
|
||||
basic_headers&
|
||||
basic_fields<Allocator>::
|
||||
operator=(basic_fields&& other) ->
|
||||
basic_fields&
|
||||
{
|
||||
if(this == &other)
|
||||
return *this;
|
||||
@@ -118,9 +118,9 @@ operator=(basic_headers&& other) ->
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
basic_headers<Allocator>::
|
||||
basic_headers(basic_headers const& other)
|
||||
: basic_headers(alloc_traits::
|
||||
basic_fields<Allocator>::
|
||||
basic_fields(basic_fields const& other)
|
||||
: basic_fields(alloc_traits::
|
||||
select_on_container_copy_construction(other.member()))
|
||||
{
|
||||
copy_from(other);
|
||||
@@ -128,9 +128,9 @@ basic_headers(basic_headers const& other)
|
||||
|
||||
template<class Allocator>
|
||||
auto
|
||||
basic_headers<Allocator>::
|
||||
operator=(basic_headers const& other) ->
|
||||
basic_headers&
|
||||
basic_fields<Allocator>::
|
||||
operator=(basic_fields const& other) ->
|
||||
basic_fields&
|
||||
{
|
||||
clear();
|
||||
copy_assign(other, std::integral_constant<bool,
|
||||
@@ -140,8 +140,8 @@ operator=(basic_headers const& other) ->
|
||||
|
||||
template<class Allocator>
|
||||
template<class OtherAlloc>
|
||||
basic_headers<Allocator>::
|
||||
basic_headers(basic_headers<OtherAlloc> const& other)
|
||||
basic_fields<Allocator>::
|
||||
basic_fields(basic_fields<OtherAlloc> const& other)
|
||||
{
|
||||
copy_from(other);
|
||||
}
|
||||
@@ -149,9 +149,9 @@ basic_headers(basic_headers<OtherAlloc> const& other)
|
||||
template<class Allocator>
|
||||
template<class OtherAlloc>
|
||||
auto
|
||||
basic_headers<Allocator>::
|
||||
operator=(basic_headers<OtherAlloc> const& other) ->
|
||||
basic_headers&
|
||||
basic_fields<Allocator>::
|
||||
operator=(basic_fields<OtherAlloc> const& other) ->
|
||||
basic_fields&
|
||||
{
|
||||
clear();
|
||||
copy_from(other);
|
||||
@@ -160,8 +160,8 @@ operator=(basic_headers<OtherAlloc> const& other) ->
|
||||
|
||||
template<class Allocator>
|
||||
template<class FwdIt>
|
||||
basic_headers<Allocator>::
|
||||
basic_headers(FwdIt first, FwdIt last)
|
||||
basic_fields<Allocator>::
|
||||
basic_fields(FwdIt first, FwdIt last)
|
||||
{
|
||||
for(;first != last; ++first)
|
||||
insert(first->name(), first->value());
|
||||
@@ -169,7 +169,7 @@ basic_headers(FwdIt first, FwdIt last)
|
||||
|
||||
template<class Allocator>
|
||||
std::size_t
|
||||
basic_headers<Allocator>::
|
||||
basic_fields<Allocator>::
|
||||
count(boost::string_ref const& name) const
|
||||
{
|
||||
auto const it = set_.find(name, less{});
|
||||
@@ -181,7 +181,7 @@ count(boost::string_ref const& name) const
|
||||
|
||||
template<class Allocator>
|
||||
auto
|
||||
basic_headers<Allocator>::
|
||||
basic_fields<Allocator>::
|
||||
find(boost::string_ref const& name) const ->
|
||||
iterator
|
||||
{
|
||||
@@ -193,7 +193,7 @@ find(boost::string_ref const& name) const ->
|
||||
|
||||
template<class Allocator>
|
||||
boost::string_ref
|
||||
basic_headers<Allocator>::
|
||||
basic_fields<Allocator>::
|
||||
operator[](boost::string_ref const& name) const
|
||||
{
|
||||
auto const it = find(name);
|
||||
@@ -204,7 +204,7 @@ operator[](boost::string_ref const& name) const
|
||||
|
||||
template<class Allocator>
|
||||
void
|
||||
basic_headers<Allocator>::
|
||||
basic_fields<Allocator>::
|
||||
clear() noexcept
|
||||
{
|
||||
delete_all();
|
||||
@@ -214,7 +214,7 @@ clear() noexcept
|
||||
|
||||
template<class Allocator>
|
||||
std::size_t
|
||||
basic_headers<Allocator>::
|
||||
basic_fields<Allocator>::
|
||||
erase(boost::string_ref const& name)
|
||||
{
|
||||
auto it = set_.find(name, less{});
|
||||
@@ -238,7 +238,7 @@ erase(boost::string_ref const& name)
|
||||
|
||||
template<class Allocator>
|
||||
void
|
||||
basic_headers<Allocator>::
|
||||
basic_fields<Allocator>::
|
||||
insert(boost::string_ref const& name,
|
||||
boost::string_ref value)
|
||||
{
|
||||
@@ -251,7 +251,7 @@ insert(boost::string_ref const& name,
|
||||
|
||||
template<class Allocator>
|
||||
void
|
||||
basic_headers<Allocator>::
|
||||
basic_fields<Allocator>::
|
||||
replace(boost::string_ref const& name,
|
||||
boost::string_ref value)
|
||||
{
|
@@ -5,6 +5,16 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||
|
||||
#include <beast/http/detail/rfc7230.hpp>
|
||||
#include <beast/core/buffer_concepts.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
|
||||
*
|
||||
* Additional changes are licensed under the same terms as NGINX and
|
||||
@@ -28,21 +38,10 @@
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
This code is a modified version of nodejs/http-parser, copyright above:
|
||||
https://github.com/nodejs/http-parser
|
||||
/* This code is a modified version of nodejs/http-parser, copyright above:
|
||||
https://github.com/nodejs/http-parser
|
||||
*/
|
||||
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||
|
||||
#include <beast/http/detail/rfc7230.hpp>
|
||||
#include <beast/core/buffer_concepts.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<bool isRequest, class Derived>
|
||||
basic_parser_v1<isRequest, Derived>::
|
||||
basic_parser_v1()
|
||||
|
@@ -20,67 +20,67 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<class Headers>
|
||||
template<class Fields>
|
||||
void
|
||||
swap(
|
||||
message_headers<true, Headers>& m1,
|
||||
message_headers<true, Headers>& m2)
|
||||
header<true, Fields>& m1,
|
||||
header<true, Fields>& m2)
|
||||
{
|
||||
using std::swap;
|
||||
swap(m1.version, m2.version);
|
||||
swap(m1.method, m2.method);
|
||||
swap(m1.url, m2.url);
|
||||
swap(m1.headers, m2.headers);
|
||||
swap(m1.fields, m2.fields);
|
||||
}
|
||||
|
||||
template<class Headers>
|
||||
template<class Fields>
|
||||
void
|
||||
swap(
|
||||
message_headers<false, Headers>& a,
|
||||
message_headers<false, Headers>& b)
|
||||
header<false, Fields>& a,
|
||||
header<false, Fields>& b)
|
||||
{
|
||||
using std::swap;
|
||||
swap(a.version, b.version);
|
||||
swap(a.status, b.status);
|
||||
swap(a.reason, b.reason);
|
||||
swap(a.headers, b.headers);
|
||||
swap(a.fields, b.fields);
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void
|
||||
swap(
|
||||
message<isRequest, Body, Headers>& m1,
|
||||
message<isRequest, Body, Headers>& m2)
|
||||
message<isRequest, Body, Fields>& m1,
|
||||
message<isRequest, Body, Fields>& m2)
|
||||
{
|
||||
using std::swap;
|
||||
swap(m1.base(), m2.base());
|
||||
swap(m1.body, m2.body);
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
bool
|
||||
is_keep_alive(message<isRequest, Body, Headers> const& msg)
|
||||
is_keep_alive(header<isRequest, Fields> const& msg)
|
||||
{
|
||||
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
|
||||
if(msg.version == 11)
|
||||
{
|
||||
if(token_list{msg.headers["Connection"]}.exists("close"))
|
||||
if(token_list{msg.fields["Connection"]}.exists("close"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if(token_list{msg.headers["Connection"]}.exists("keep-alive"))
|
||||
if(token_list{msg.fields["Connection"]}.exists("keep-alive"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
bool
|
||||
is_upgrade(message<isRequest, Body, Headers> const& msg)
|
||||
is_upgrade(header<isRequest, Fields> const& msg)
|
||||
{
|
||||
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
|
||||
if(msg.version == 10)
|
||||
return false;
|
||||
if(token_list{msg.headers["Connection"]}.exists("upgrade"))
|
||||
if(token_list{msg.fields["Connection"]}.exists("upgrade"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -93,19 +93,19 @@ struct prepare_info
|
||||
boost::optional<std::uint64_t> content_length;
|
||||
};
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
inline
|
||||
void
|
||||
prepare_options(prepare_info& pi,
|
||||
message<isRequest, Body, Headers>& msg)
|
||||
message<isRequest, Body, Fields>& msg)
|
||||
{
|
||||
beast::detail::ignore_unused(pi, msg);
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void
|
||||
prepare_option(prepare_info& pi,
|
||||
message<isRequest, Body, Headers>& msg,
|
||||
message<isRequest, Body, Fields>& msg,
|
||||
connection value)
|
||||
{
|
||||
beast::detail::ignore_unused(msg);
|
||||
@@ -113,11 +113,11 @@ prepare_option(prepare_info& pi,
|
||||
}
|
||||
|
||||
template<
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class Opt, class... Opts>
|
||||
void
|
||||
prepare_options(prepare_info& pi,
|
||||
message<isRequest, Body, Headers>& msg,
|
||||
message<isRequest, Body, Fields>& msg,
|
||||
Opt&& opt, Opts&&... opts)
|
||||
{
|
||||
prepare_option(pi, msg, opt);
|
||||
@@ -125,10 +125,10 @@ prepare_options(prepare_info& pi,
|
||||
std::forward<Opts>(opts)...);
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void
|
||||
prepare_content_length(prepare_info& pi,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message<isRequest, Body, Fields> const& msg,
|
||||
std::true_type)
|
||||
{
|
||||
typename Body::writer w(msg);
|
||||
@@ -140,10 +140,10 @@ prepare_content_length(prepare_info& pi,
|
||||
pi.content_length = w.content_length();
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void
|
||||
prepare_content_length(prepare_info& pi,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message<isRequest, Body, Fields> const& msg,
|
||||
std::false_type)
|
||||
{
|
||||
beast::detail::ignore_unused(msg);
|
||||
@@ -153,10 +153,10 @@ prepare_content_length(prepare_info& pi,
|
||||
} // detail
|
||||
|
||||
template<
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class... Options>
|
||||
void
|
||||
prepare(message<isRequest, Body, Headers>& msg,
|
||||
prepare(message<isRequest, Body, Fields>& msg,
|
||||
Options&&... options)
|
||||
{
|
||||
// VFALCO TODO
|
||||
@@ -165,7 +165,7 @@ prepare(message<isRequest, Body, Headers>& msg,
|
||||
static_assert(has_writer<Body>::value,
|
||||
"Body has no writer");
|
||||
static_assert(is_Writer<typename Body::writer,
|
||||
message<isRequest, Body, Headers>>::value,
|
||||
message<isRequest, Body, Fields>>::value,
|
||||
"Writer requirements not met");
|
||||
detail::prepare_info pi;
|
||||
detail::prepare_content_length(pi, msg,
|
||||
@@ -173,15 +173,15 @@ prepare(message<isRequest, Body, Headers>& msg,
|
||||
detail::prepare_options(pi, msg,
|
||||
std::forward<Options>(options)...);
|
||||
|
||||
if(msg.headers.exists("Connection"))
|
||||
if(msg.fields.exists("Connection"))
|
||||
throw std::invalid_argument(
|
||||
"prepare called with Connection field set");
|
||||
|
||||
if(msg.headers.exists("Content-Length"))
|
||||
if(msg.fields.exists("Content-Length"))
|
||||
throw std::invalid_argument(
|
||||
"prepare called with Content-Length field set");
|
||||
|
||||
if(token_list{msg.headers["Transfer-Encoding"]}.exists("chunked"))
|
||||
if(token_list{msg.fields["Transfer-Encoding"]}.exists("chunked"))
|
||||
throw std::invalid_argument(
|
||||
"prepare called with Transfer-Encoding: chunked set");
|
||||
|
||||
@@ -192,27 +192,27 @@ prepare(message<isRequest, Body, Headers>& msg,
|
||||
struct set_field
|
||||
{
|
||||
void
|
||||
operator()(message<true, Body, Headers>& msg,
|
||||
operator()(message<true, Body, Fields>& msg,
|
||||
detail::prepare_info const& pi) const
|
||||
{
|
||||
using beast::detail::ci_equal;
|
||||
if(*pi.content_length > 0 ||
|
||||
ci_equal(msg.method, "POST"))
|
||||
{
|
||||
msg.headers.insert(
|
||||
msg.fields.insert(
|
||||
"Content-Length", *pi.content_length);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
operator()(message<false, Body, Headers>& msg,
|
||||
operator()(message<false, Body, Fields>& msg,
|
||||
detail::prepare_info const& pi) const
|
||||
{
|
||||
if((msg.status / 100 ) != 1 &&
|
||||
msg.status != 204 &&
|
||||
msg.status != 304)
|
||||
{
|
||||
msg.headers.insert(
|
||||
msg.fields.insert(
|
||||
"Content-Length", *pi.content_length);
|
||||
}
|
||||
}
|
||||
@@ -221,39 +221,39 @@ prepare(message<isRequest, Body, Headers>& msg,
|
||||
}
|
||||
else if(msg.version >= 11)
|
||||
{
|
||||
msg.headers.insert("Transfer-Encoding", "chunked");
|
||||
msg.fields.insert("Transfer-Encoding", "chunked");
|
||||
}
|
||||
}
|
||||
|
||||
auto const content_length =
|
||||
msg.headers.exists("Content-Length");
|
||||
msg.fields.exists("Content-Length");
|
||||
|
||||
if(pi.connection_value)
|
||||
{
|
||||
switch(*pi.connection_value)
|
||||
{
|
||||
case connection::upgrade:
|
||||
msg.headers.insert("Connection", "upgrade");
|
||||
msg.fields.insert("Connection", "upgrade");
|
||||
break;
|
||||
|
||||
case connection::keep_alive:
|
||||
if(msg.version < 11)
|
||||
{
|
||||
if(content_length)
|
||||
msg.headers.insert("Connection", "keep-alive");
|
||||
msg.fields.insert("Connection", "keep-alive");
|
||||
}
|
||||
break;
|
||||
|
||||
case connection::close:
|
||||
if(msg.version >= 11)
|
||||
msg.headers.insert("Connection", "close");
|
||||
msg.fields.insert("Connection", "close");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rfc7230 6.7.
|
||||
if(msg.version < 11 && token_list{
|
||||
msg.headers["Connection"]}.exists("upgrade"))
|
||||
msg.fields["Connection"]}.exists("upgrade"))
|
||||
throw std::invalid_argument(
|
||||
"invalid version for Connection: upgrade");
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ public:
|
||||
case parse_error::invalid_chunk_size: return "invalid chunk size";
|
||||
case parse_error::invalid_ext_name: return "invalid ext name";
|
||||
case parse_error::invalid_ext_val: return "invalid ext val";
|
||||
case parse_error::headers_too_big: return "headers size limit exceeded";
|
||||
case parse_error::header_too_big: return "header size limit exceeded";
|
||||
case parse_error::body_too_big: return "body size limit exceeded";
|
||||
default:
|
||||
case parse_error::short_read: return "unexpected end of data";
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#define BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||
|
||||
#include <beast/http/concepts.hpp>
|
||||
#include <beast/http/headers_parser_v1.hpp>
|
||||
#include <beast/http/header_parser_v1.hpp>
|
||||
#include <beast/http/parse.hpp>
|
||||
#include <beast/http/parser_v1.hpp>
|
||||
#include <beast/core/bind_handler.hpp>
|
||||
@@ -23,18 +23,18 @@ namespace http {
|
||||
namespace detail {
|
||||
|
||||
template<class Stream, class DynamicBuffer,
|
||||
bool isRequest, class Headers,
|
||||
bool isRequest, class Fields,
|
||||
class Handler>
|
||||
class read_headers_op
|
||||
class read_header_op
|
||||
{
|
||||
using alloc_type =
|
||||
handler_alloc<char, Handler>;
|
||||
|
||||
using parser_type =
|
||||
headers_parser_v1<isRequest, Headers>;
|
||||
header_parser_v1<isRequest, Fields>;
|
||||
|
||||
using message_type =
|
||||
message_headers<isRequest, Headers>;
|
||||
header<isRequest, Fields>;
|
||||
|
||||
struct data
|
||||
{
|
||||
@@ -63,11 +63,11 @@ class read_headers_op
|
||||
std::shared_ptr<data> d_;
|
||||
|
||||
public:
|
||||
read_headers_op(read_headers_op&&) = default;
|
||||
read_headers_op(read_headers_op const&) = default;
|
||||
read_header_op(read_header_op&&) = default;
|
||||
read_header_op(read_header_op const&) = default;
|
||||
|
||||
template<class DeducedHandler, class... Args>
|
||||
read_headers_op(
|
||||
read_header_op(
|
||||
DeducedHandler&& h, Stream& s, Args&&... args)
|
||||
: d_(std::allocate_shared<data>(alloc_type{h},
|
||||
std::forward<DeducedHandler>(h), s,
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
|
||||
friend
|
||||
void* asio_handler_allocate(
|
||||
std::size_t size, read_headers_op* op)
|
||||
std::size_t size, read_header_op* op)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate(size, op->d_->h);
|
||||
@@ -89,21 +89,21 @@ public:
|
||||
|
||||
friend
|
||||
void asio_handler_deallocate(
|
||||
void* p, std::size_t size, read_headers_op* op)
|
||||
void* p, std::size_t size, read_header_op* op)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
deallocate(p, size, op->d_->h);
|
||||
}
|
||||
|
||||
friend
|
||||
bool asio_handler_is_continuation(read_headers_op* op)
|
||||
bool asio_handler_is_continuation(read_header_op* op)
|
||||
{
|
||||
return op->d_->cont;
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
friend
|
||||
void asio_handler_invoke(Function&& f, read_headers_op* op)
|
||||
void asio_handler_invoke(Function&& f, read_header_op* op)
|
||||
{
|
||||
return boost_asio_handler_invoke_helpers::
|
||||
invoke(f, op->d_->h);
|
||||
@@ -111,10 +111,10 @@ public:
|
||||
};
|
||||
|
||||
template<class Stream, class DynamicBuffer,
|
||||
bool isRequest, class Headers,
|
||||
bool isRequest, class Fields,
|
||||
class Handler>
|
||||
void
|
||||
read_headers_op<Stream, DynamicBuffer, isRequest, Headers, Handler>::
|
||||
read_header_op<Stream, DynamicBuffer, isRequest, Fields, Handler>::
|
||||
operator()(error_code ec, bool again)
|
||||
{
|
||||
auto& d = *d_;
|
||||
@@ -141,10 +141,10 @@ operator()(error_code ec, bool again)
|
||||
} // detail
|
||||
|
||||
template<class SyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Headers>
|
||||
bool isRequest, class Fields>
|
||||
void
|
||||
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message_headers<isRequest, Headers>& msg)
|
||||
header<isRequest, Fields>& msg)
|
||||
{
|
||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
@@ -157,17 +157,17 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
}
|
||||
|
||||
template<class SyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Headers>
|
||||
bool isRequest, class Fields>
|
||||
void
|
||||
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message_headers<isRequest, Headers>& m,
|
||||
header<isRequest, Fields>& m,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
|
||||
"DynamicBuffer requirements not met");
|
||||
headers_parser_v1<isRequest, Headers> p;
|
||||
header_parser_v1<isRequest, Fields> p;
|
||||
beast::http::parse(stream, dynabuf, p, ec);
|
||||
if(ec)
|
||||
return;
|
||||
@@ -176,12 +176,12 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
}
|
||||
|
||||
template<class AsyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Headers,
|
||||
bool isRequest, class Fields,
|
||||
class ReadHandler>
|
||||
typename async_completion<
|
||||
ReadHandler, void(error_code)>::result_type
|
||||
async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message_headers<isRequest, Headers>& m,
|
||||
header<isRequest, Fields>& m,
|
||||
ReadHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
||||
@@ -190,8 +190,8 @@ async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
"DynamicBuffer requirements not met");
|
||||
beast::async_completion<ReadHandler,
|
||||
void(error_code)> completion(handler);
|
||||
detail::read_headers_op<AsyncReadStream, DynamicBuffer,
|
||||
isRequest, Headers, decltype(
|
||||
detail::read_header_op<AsyncReadStream, DynamicBuffer,
|
||||
isRequest, Fields, decltype(
|
||||
completion.handler)>{completion.handler,
|
||||
stream, dynabuf, m};
|
||||
return completion.result.get();
|
||||
@@ -202,7 +202,7 @@ async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
namespace detail {
|
||||
|
||||
template<class Stream, class DynamicBuffer,
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class Handler>
|
||||
class read_op
|
||||
{
|
||||
@@ -210,10 +210,10 @@ class read_op
|
||||
handler_alloc<char, Handler>;
|
||||
|
||||
using parser_type =
|
||||
parser_v1<isRequest, Body, Headers>;
|
||||
parser_v1<isRequest, Body, Fields>;
|
||||
|
||||
using message_type =
|
||||
message<isRequest, Body, Headers>;
|
||||
message<isRequest, Body, Fields>;
|
||||
|
||||
struct data
|
||||
{
|
||||
@@ -289,10 +289,10 @@ public:
|
||||
};
|
||||
|
||||
template<class Stream, class DynamicBuffer,
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class Handler>
|
||||
void
|
||||
read_op<Stream, DynamicBuffer, isRequest, Body, Headers, Handler>::
|
||||
read_op<Stream, DynamicBuffer, isRequest, Body, Fields, Handler>::
|
||||
operator()(error_code ec, bool again)
|
||||
{
|
||||
auto& d = *d_;
|
||||
@@ -319,10 +319,10 @@ operator()(error_code ec, bool again)
|
||||
} // detail
|
||||
|
||||
template<class SyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
void
|
||||
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message<isRequest, Body, Headers>& msg)
|
||||
message<isRequest, Body, Fields>& msg)
|
||||
{
|
||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
@@ -333,7 +333,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
static_assert(has_reader<Body>::value,
|
||||
"Body has no reader");
|
||||
static_assert(is_Reader<typename Body::reader,
|
||||
message<isRequest, Body, Headers>>::value,
|
||||
message<isRequest, Body, Fields>>::value,
|
||||
"Reader requirements not met");
|
||||
error_code ec;
|
||||
beast::http::read(stream, dynabuf, msg, ec);
|
||||
@@ -342,10 +342,10 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
}
|
||||
|
||||
template<class SyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
void
|
||||
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message<isRequest, Body, Headers>& m,
|
||||
message<isRequest, Body, Fields>& m,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||
@@ -357,9 +357,9 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
static_assert(has_reader<Body>::value,
|
||||
"Body has no reader");
|
||||
static_assert(is_Reader<typename Body::reader,
|
||||
message<isRequest, Body, Headers>>::value,
|
||||
message<isRequest, Body, Fields>>::value,
|
||||
"Reader requirements not met");
|
||||
parser_v1<isRequest, Body, Headers> p;
|
||||
parser_v1<isRequest, Body, Fields> p;
|
||||
beast::http::parse(stream, dynabuf, p, ec);
|
||||
if(ec)
|
||||
return;
|
||||
@@ -368,12 +368,12 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
}
|
||||
|
||||
template<class AsyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class ReadHandler>
|
||||
typename async_completion<
|
||||
ReadHandler, void(error_code)>::result_type
|
||||
async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message<isRequest, Body, Headers>& m,
|
||||
message<isRequest, Body, Fields>& m,
|
||||
ReadHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
||||
@@ -385,12 +385,12 @@ async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
static_assert(has_reader<Body>::value,
|
||||
"Body has no reader");
|
||||
static_assert(is_Reader<typename Body::reader,
|
||||
message<isRequest, Body, Headers>>::value,
|
||||
message<isRequest, Body, Fields>>::value,
|
||||
"Reader requirements not met");
|
||||
beast::async_completion<ReadHandler,
|
||||
void(error_code)> completion(handler);
|
||||
detail::read_op<AsyncReadStream, DynamicBuffer,
|
||||
isRequest, Body, Headers, decltype(
|
||||
isRequest, Body, Fields, decltype(
|
||||
completion.handler)>{completion.handler,
|
||||
stream, dynabuf, m};
|
||||
return completion.result.get();
|
||||
|
@@ -32,10 +32,10 @@ namespace http {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class DynamicBuffer, class Headers>
|
||||
template<class DynamicBuffer, class Fields>
|
||||
void
|
||||
write_start_line(DynamicBuffer& dynabuf,
|
||||
message_headers<true, Headers> const& msg)
|
||||
header<true, Fields> const& msg)
|
||||
{
|
||||
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
|
||||
write(dynabuf, msg.method);
|
||||
@@ -52,10 +52,10 @@ write_start_line(DynamicBuffer& dynabuf,
|
||||
}
|
||||
}
|
||||
|
||||
template<class DynamicBuffer, class Headers>
|
||||
template<class DynamicBuffer, class Fields>
|
||||
void
|
||||
write_start_line(DynamicBuffer& dynabuf,
|
||||
message_headers<false, Headers> const& msg)
|
||||
header<false, Fields> const& msg)
|
||||
{
|
||||
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
|
||||
switch(msg.version)
|
||||
@@ -205,10 +205,10 @@ operator()(error_code ec, std::size_t, bool again)
|
||||
} // detail
|
||||
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Headers>
|
||||
bool isRequest, class Fields>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message_headers<isRequest, Headers> const& msg)
|
||||
header<isRequest, Fields> const& msg)
|
||||
{
|
||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||
"SyncWriteStream requirements not met");
|
||||
@@ -219,28 +219,28 @@ write(SyncWriteStream& stream,
|
||||
}
|
||||
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Headers>
|
||||
bool isRequest, class Fields>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message_headers<isRequest, Headers> const& msg,
|
||||
header<isRequest, Fields> const& msg,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||
"SyncWriteStream requirements not met");
|
||||
streambuf sb;
|
||||
detail::write_start_line(sb, msg);
|
||||
detail::write_fields(sb, msg.headers);
|
||||
detail::write_fields(sb, msg.fields);
|
||||
beast::write(sb, "\r\n");
|
||||
boost::asio::write(stream, sb.data(), ec);
|
||||
}
|
||||
|
||||
template<class AsyncWriteStream,
|
||||
bool isRequest, class Headers,
|
||||
bool isRequest, class Fields,
|
||||
class WriteHandler>
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
async_write(AsyncWriteStream& stream,
|
||||
message_headers<isRequest, Headers> const& msg,
|
||||
header<isRequest, Fields> const& msg,
|
||||
WriteHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncWriteStream<AsyncWriteStream>::value,
|
||||
@@ -249,7 +249,7 @@ async_write(AsyncWriteStream& stream,
|
||||
void(error_code)> completion(handler);
|
||||
streambuf sb;
|
||||
detail::write_start_line(sb, msg);
|
||||
detail::write_fields(sb, msg.headers);
|
||||
detail::write_fields(sb, msg.fields);
|
||||
beast::write(sb, "\r\n");
|
||||
detail::write_streambuf_op<AsyncWriteStream,
|
||||
decltype(completion.handler)>{
|
||||
@@ -261,10 +261,10 @@ async_write(AsyncWriteStream& stream,
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
struct write_preparation
|
||||
{
|
||||
message<isRequest, Body, Headers> const& msg;
|
||||
message<isRequest, Body, Fields> const& msg;
|
||||
typename Body::writer w;
|
||||
streambuf sb;
|
||||
bool chunked;
|
||||
@@ -272,14 +272,14 @@ struct write_preparation
|
||||
|
||||
explicit
|
||||
write_preparation(
|
||||
message<isRequest, Body, Headers> const& msg_)
|
||||
message<isRequest, Body, Fields> const& msg_)
|
||||
: msg(msg_)
|
||||
, w(msg)
|
||||
, chunked(token_list{
|
||||
msg.headers["Transfer-Encoding"]}.exists("chunked"))
|
||||
msg.fields["Transfer-Encoding"]}.exists("chunked"))
|
||||
, close(token_list{
|
||||
msg.headers["Connection"]}.exists("close") ||
|
||||
(msg.version < 11 && ! msg.headers.exists(
|
||||
msg.fields["Connection"]}.exists("close") ||
|
||||
(msg.version < 11 && ! msg.fields.exists(
|
||||
"Content-Length")))
|
||||
{
|
||||
}
|
||||
@@ -292,13 +292,13 @@ struct write_preparation
|
||||
return;
|
||||
|
||||
write_start_line(sb, msg);
|
||||
write_fields(sb, msg.headers);
|
||||
write_fields(sb, msg.fields);
|
||||
beast::write(sb, "\r\n");
|
||||
}
|
||||
};
|
||||
|
||||
template<class Stream, class Handler,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
class write_op
|
||||
{
|
||||
using alloc_type =
|
||||
@@ -309,7 +309,7 @@ class write_op
|
||||
Stream& s;
|
||||
// VFALCO How do we use handler_alloc in write_preparation?
|
||||
write_preparation<
|
||||
isRequest, Body, Headers> wp;
|
||||
isRequest, Body, Fields> wp;
|
||||
Handler h;
|
||||
resume_context resume;
|
||||
resume_context copy;
|
||||
@@ -318,7 +318,7 @@ class write_op
|
||||
|
||||
template<class DeducedHandler>
|
||||
data(DeducedHandler&& h_, Stream& s_,
|
||||
message<isRequest, Body, Headers> const& m_)
|
||||
message<isRequest, Body, Fields> const& m_)
|
||||
: s(s_)
|
||||
, wp(m_)
|
||||
, h(std::forward<DeducedHandler>(h_))
|
||||
@@ -343,7 +343,7 @@ class write_op
|
||||
void operator()(ConstBufferSequence const& buffers) const
|
||||
{
|
||||
auto& d = *self_.d_;
|
||||
// write headers and body
|
||||
// write header and body
|
||||
if(d.wp.chunked)
|
||||
boost::asio::async_write(d.s,
|
||||
buffer_cat(d.wp.sb.data(),
|
||||
@@ -451,9 +451,9 @@ public:
|
||||
};
|
||||
|
||||
template<class Stream, class Handler,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
void
|
||||
write_op<Stream, Handler, isRequest, Body, Headers>::
|
||||
write_op<Stream, Handler, isRequest, Body, Fields>::
|
||||
operator()(error_code ec, std::size_t, bool again)
|
||||
{
|
||||
auto& d = *d_;
|
||||
@@ -502,7 +502,7 @@ operator()(error_code ec, std::size_t, bool again)
|
||||
return;
|
||||
}
|
||||
|
||||
// sent headers and body
|
||||
// sent header and body
|
||||
case 2:
|
||||
d.wp.sb.consume(d.wp.sb.size());
|
||||
d.state = 3;
|
||||
@@ -578,7 +578,7 @@ public:
|
||||
template<class ConstBufferSequence>
|
||||
void operator()(ConstBufferSequence const& buffers) const
|
||||
{
|
||||
// write headers and body
|
||||
// write header and body
|
||||
if(chunked_)
|
||||
boost::asio::write(stream_, buffer_cat(
|
||||
sb_.data(), chunk_encode(false, buffers)), ec_);
|
||||
@@ -619,10 +619,10 @@ public:
|
||||
} // detail
|
||||
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg)
|
||||
message<isRequest, Body, Fields> const& msg)
|
||||
{
|
||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||
"SyncWriteStream requirements not met");
|
||||
@@ -631,7 +631,7 @@ write(SyncWriteStream& stream,
|
||||
static_assert(has_writer<Body>::value,
|
||||
"Body has no writer");
|
||||
static_assert(is_Writer<typename Body::writer,
|
||||
message<isRequest, Body, Headers>>::value,
|
||||
message<isRequest, Body, Fields>>::value,
|
||||
"Writer requirements not met");
|
||||
error_code ec;
|
||||
write(stream, msg, ec);
|
||||
@@ -640,10 +640,10 @@ write(SyncWriteStream& stream,
|
||||
}
|
||||
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message<isRequest, Body, Fields> const& msg,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||
@@ -653,9 +653,9 @@ write(SyncWriteStream& stream,
|
||||
static_assert(has_writer<Body>::value,
|
||||
"Body has no writer");
|
||||
static_assert(is_Writer<typename Body::writer,
|
||||
message<isRequest, Body, Headers>>::value,
|
||||
message<isRequest, Body, Fields>>::value,
|
||||
"Writer requirements not met");
|
||||
detail::write_preparation<isRequest, Body, Headers> wp(msg);
|
||||
detail::write_preparation<isRequest, Body, Fields> wp(msg);
|
||||
wp.init(ec);
|
||||
if(ec)
|
||||
return;
|
||||
@@ -729,12 +729,12 @@ write(SyncWriteStream& stream,
|
||||
}
|
||||
|
||||
template<class AsyncWriteStream,
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class WriteHandler>
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
async_write(AsyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message<isRequest, Body, Fields> const& msg,
|
||||
WriteHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncWriteStream<AsyncWriteStream>::value,
|
||||
@@ -744,21 +744,21 @@ async_write(AsyncWriteStream& stream,
|
||||
static_assert(has_writer<Body>::value,
|
||||
"Body has no writer");
|
||||
static_assert(is_Writer<typename Body::writer,
|
||||
message<isRequest, Body, Headers>>::value,
|
||||
message<isRequest, Body, Fields>>::value,
|
||||
"Writer requirements not met");
|
||||
beast::async_completion<WriteHandler,
|
||||
void(error_code)> completion(handler);
|
||||
detail::write_op<AsyncWriteStream, decltype(completion.handler),
|
||||
isRequest, Body, Headers>{completion.handler, stream, msg};
|
||||
isRequest, Body, Fields>{completion.handler, stream, msg};
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<bool isRequest, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message_headers<isRequest, Headers> const& msg)
|
||||
header<isRequest, Fields> const& msg)
|
||||
{
|
||||
beast::detail::sync_ostream oss{os};
|
||||
error_code ec;
|
||||
@@ -768,17 +768,17 @@ operator<<(std::ostream& os,
|
||||
return os;
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message<isRequest, Body, Headers> const& msg)
|
||||
message<isRequest, Body, Fields> const& msg)
|
||||
{
|
||||
static_assert(is_Body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(has_writer<Body>::value,
|
||||
"Body has no writer");
|
||||
static_assert(is_Writer<typename Body::writer,
|
||||
message<isRequest, Body, Headers>>::value,
|
||||
message<isRequest, Body, Fields>>::value,
|
||||
"Writer requirements not met");
|
||||
beast::detail::sync_ostream oss{os};
|
||||
error_code ec;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
#ifndef BEAST_HTTP_MESSAGE_HPP
|
||||
#define BEAST_HTTP_MESSAGE_HPP
|
||||
|
||||
#include <beast/http/basic_headers.hpp>
|
||||
#include <beast/http/fields.hpp>
|
||||
#include <beast/core/detail/integer_sequence.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -19,27 +19,30 @@ namespace beast {
|
||||
namespace http {
|
||||
|
||||
#if GENERATING_DOCS
|
||||
/** A container for HTTP request or response headers.
|
||||
/** A container for a HTTP request or response header.
|
||||
|
||||
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".
|
||||
A header includes the Start Line and Fields.
|
||||
|
||||
Some use-cases:
|
||||
|
||||
@li When the message has no body, such as a response to a HEAD request.
|
||||
|
||||
@li When the caller wishes to defer instantiation of the body.
|
||||
|
||||
@li Invoke algorithms which operate on the header only.
|
||||
*/
|
||||
template<bool isRequest, class Headers>
|
||||
struct message_headers
|
||||
template<bool isRequest, class Fields>
|
||||
struct header
|
||||
|
||||
#else
|
||||
template<bool isRequest, class Headers>
|
||||
struct message_headers;
|
||||
template<bool isRequest, class Fields>
|
||||
struct header;
|
||||
|
||||
template<class Headers>
|
||||
struct message_headers<true, Headers>
|
||||
template<class Fields>
|
||||
struct header<true, Fields>
|
||||
#endif
|
||||
{
|
||||
/// Indicates if the message headers are a request or response.
|
||||
/// Indicates if the header is a request or response.
|
||||
#if GENERATING_DOCS
|
||||
static bool constexpr is_request = isRequest;
|
||||
|
||||
@@ -47,8 +50,8 @@ struct message_headers<true, Headers>
|
||||
static bool constexpr is_request = true;
|
||||
#endif
|
||||
|
||||
/// The type representing the headers.
|
||||
using headers_type = Headers;
|
||||
/// The type representing the fields.
|
||||
using fields_type = Fields;
|
||||
|
||||
/** The HTTP version.
|
||||
|
||||
@@ -74,67 +77,71 @@ struct message_headers<true, Headers>
|
||||
std::string url;
|
||||
|
||||
/// The HTTP field values.
|
||||
Headers headers;
|
||||
fields_type fields;
|
||||
|
||||
/// Default constructor
|
||||
message_headers() = default;
|
||||
header() = default;
|
||||
|
||||
/// Move constructor
|
||||
message_headers(message_headers&&) = default;
|
||||
header(header&&) = default;
|
||||
|
||||
/// Copy constructor
|
||||
message_headers(message_headers const&) = default;
|
||||
header(header const&) = default;
|
||||
|
||||
/// Move assignment
|
||||
message_headers& operator=(message_headers&&) = default;
|
||||
header& operator=(header&&) = default;
|
||||
|
||||
/// Copy assignment
|
||||
message_headers& operator=(message_headers const&) = default;
|
||||
header& operator=(header const&) = default;
|
||||
|
||||
/** Construct message headers.
|
||||
/** Construct the header.
|
||||
|
||||
All arguments are forwarded to the constructor
|
||||
of the `headers` member.
|
||||
of the `fields` member.
|
||||
|
||||
@note This constructor participates in overload resolution
|
||||
if and only if the first parameter is not convertible to
|
||||
`message_headers`.
|
||||
`header`.
|
||||
*/
|
||||
#if GENERATING_DOCS
|
||||
template<class... Args>
|
||||
explicit
|
||||
message_headers(Args&&... args);
|
||||
header(Args&&... args);
|
||||
|
||||
#else
|
||||
template<class Arg1, class... ArgN,
|
||||
class = typename std::enable_if<
|
||||
(sizeof...(ArgN) > 0) || ! std::is_convertible<
|
||||
typename std::decay<Arg1>::type,
|
||||
message_headers>::value>::type>
|
||||
header>::value>::type>
|
||||
explicit
|
||||
message_headers(Arg1&& arg1, ArgN&&... argn)
|
||||
: headers(std::forward<Arg1>(arg1),
|
||||
header(Arg1&& arg1, ArgN&&... argn)
|
||||
: fields(std::forward<Arg1>(arg1),
|
||||
std::forward<ArgN>(argn)...)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** A container for HTTP request or response headers.
|
||||
/** A container for a HTTP request or response header.
|
||||
|
||||
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.
|
||||
A header includes the Start Line and Fields.
|
||||
|
||||
Some use-cases:
|
||||
|
||||
@li When the message has no body, such as a response to a HEAD request.
|
||||
|
||||
@li When the caller wishes to defer instantiation of the body.
|
||||
|
||||
@li Invoke algorithms which operate on the header only.
|
||||
*/
|
||||
template<class Headers>
|
||||
struct message_headers<false, Headers>
|
||||
template<class Fields>
|
||||
struct header<false, Fields>
|
||||
{
|
||||
/// Indicates if the message headers are a request or response.
|
||||
/// Indicates if the header is a request or response.
|
||||
static bool constexpr is_request = false;
|
||||
|
||||
/// The type representing the headers.
|
||||
using headers_type = Headers;
|
||||
/// The type representing the fields.
|
||||
using fields_type = Fields;
|
||||
|
||||
/** The HTTP version.
|
||||
|
||||
@@ -148,40 +155,40 @@ struct message_headers<false, Headers>
|
||||
int version;
|
||||
|
||||
/// The HTTP field values.
|
||||
Headers headers;
|
||||
fields_type fields;
|
||||
|
||||
/// Default constructor
|
||||
message_headers() = default;
|
||||
header() = default;
|
||||
|
||||
/// Move constructor
|
||||
message_headers(message_headers&&) = default;
|
||||
header(header&&) = default;
|
||||
|
||||
/// Copy constructor
|
||||
message_headers(message_headers const&) = default;
|
||||
header(header const&) = default;
|
||||
|
||||
/// Move assignment
|
||||
message_headers& operator=(message_headers&&) = default;
|
||||
header& operator=(header&&) = default;
|
||||
|
||||
/// Copy assignment
|
||||
message_headers& operator=(message_headers const&) = default;
|
||||
header& operator=(header const&) = default;
|
||||
|
||||
/** Construct message headers.
|
||||
/** Construct the header.
|
||||
|
||||
All arguments are forwarded to the constructor
|
||||
of the `headers` member.
|
||||
of the `fields` member.
|
||||
|
||||
@note This constructor participates in overload resolution
|
||||
if and only if the first parameter is not convertible to
|
||||
`message_headers`.
|
||||
`header`.
|
||||
*/
|
||||
template<class Arg1, class... ArgN,
|
||||
class = typename std::enable_if<
|
||||
(sizeof...(ArgN) > 0) || ! std::is_convertible<
|
||||
typename std::decay<Arg1>::type,
|
||||
message_headers>::value>::type>
|
||||
header>::value>::type>
|
||||
explicit
|
||||
message_headers(Arg1&& arg1, ArgN&&... argn)
|
||||
: headers(std::forward<Arg1>(arg1),
|
||||
header(Arg1&& arg1, ArgN&&... argn)
|
||||
: fields(std::forward<Arg1>(arg1),
|
||||
std::forward<ArgN>(argn)...)
|
||||
{
|
||||
}
|
||||
@@ -204,9 +211,10 @@ struct message_headers<false, Headers>
|
||||
|
||||
/** A container for a complete HTTP 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.
|
||||
A message can be a request or response, depending on the
|
||||
`isRequest` template argument value. Requests and responses
|
||||
have different types; functions may be overloaded based on
|
||||
the type if desired.
|
||||
|
||||
The `Body` template argument type determines the model used
|
||||
to read or write the content body of the message.
|
||||
@@ -217,19 +225,18 @@ struct message_headers<false, Headers>
|
||||
|
||||
@tparam Body A type meeting the requirements of Body.
|
||||
|
||||
@tparam Headers The type of container used to hold the
|
||||
@tparam Fields The type of container used to hold the
|
||||
field value pairs.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
struct message :
|
||||
message_headers<isRequest, Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
struct message : header<isRequest, Fields>
|
||||
{
|
||||
/// The base class used to hold the request or response headers
|
||||
using base_type = message_headers<isRequest, Headers>;
|
||||
/// The base class used to hold the header portion of the message.
|
||||
using base_type = header<isRequest, Fields>;
|
||||
|
||||
/** The type providing the body traits.
|
||||
|
||||
The `body` member will be of type `body_type::value_type`.
|
||||
The @ref message::body member will be of type `body_type::value_type`.
|
||||
*/
|
||||
using body_type = Body;
|
||||
|
||||
@@ -239,7 +246,7 @@ struct message :
|
||||
/// Default constructor
|
||||
message() = default;
|
||||
|
||||
/** Construct a message from message headers.
|
||||
/** Construct a message from a header.
|
||||
|
||||
Additional arguments, if any, are forwarded to
|
||||
the constructor of the body member.
|
||||
@@ -252,7 +259,7 @@ struct message :
|
||||
{
|
||||
}
|
||||
|
||||
/** Construct a message from message headers.
|
||||
/** Construct a message from a header.
|
||||
|
||||
Additional arguments, if any, are forwarded to
|
||||
the constructor of the body member.
|
||||
@@ -288,7 +295,7 @@ struct message :
|
||||
|
||||
@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 fields constructor.
|
||||
|
||||
@note This constructor participates in overload resolution
|
||||
only if `u` is not convertible to `base_type`.
|
||||
@@ -320,7 +327,7 @@ struct message :
|
||||
|
||||
@param un A tuple forwarded as a parameter pack to the body constructor.
|
||||
|
||||
@param vn A tuple forwarded as a parameter pack to the headers constructor.
|
||||
@param vn A tuple forwarded as a parameter pack to the fields constructor.
|
||||
*/
|
||||
template<class... Un, class... Vn>
|
||||
message(std::piecewise_construct_t,
|
||||
@@ -331,14 +338,14 @@ struct message :
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the message headers portion of the message
|
||||
/// Returns the header portion of the message
|
||||
base_type&
|
||||
base()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Returns the message headers portion of the message
|
||||
/// Returns the header portion of the message
|
||||
base_type const&
|
||||
base() const
|
||||
{
|
||||
@@ -368,64 +375,60 @@ private:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if GENERATING_DOCS
|
||||
/** Swap two HTTP message headers.
|
||||
/** Swap two header objects.
|
||||
|
||||
@par Requirements
|
||||
`Headers` is @b Swappable.
|
||||
`Fields` is @b Swappable.
|
||||
*/
|
||||
template<bool isRequest, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
void
|
||||
swap(
|
||||
message_headers<isRequest, Headers>& m1,
|
||||
message_headers<isRequest, Headers>& m2);
|
||||
header<isRequest, Fields>& m1,
|
||||
header<isRequest, Fields>& m2);
|
||||
#endif
|
||||
|
||||
/** Swap two HTTP messages.
|
||||
/** Swap two message objects.
|
||||
|
||||
@par Requirements:
|
||||
`Body` and `Headers` are @b Swappable.
|
||||
`Body::value_type` and `Fields` are @b Swappable.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void
|
||||
swap(
|
||||
message<isRequest, Body, Headers>& m1,
|
||||
message<isRequest, Body, Headers>& m2);
|
||||
message<isRequest, Body, Fields>& m1,
|
||||
message<isRequest, Body, Fields>& m2);
|
||||
|
||||
/// Message headers for a typical HTTP request
|
||||
using request_headers = message_headers<true,
|
||||
basic_headers<std::allocator<char>>>;
|
||||
/// A typical HTTP request header
|
||||
using request_header = header<true, fields>;
|
||||
|
||||
/// Message headers for a typical HTTP response
|
||||
using response_headers = message_headers<false,
|
||||
basic_headers<std::allocator<char>>>;
|
||||
/// Typical HTTP response header
|
||||
using response_header = header<false, fields>;
|
||||
|
||||
/// A typical HTTP request message
|
||||
template<class Body,
|
||||
class Headers = basic_headers<std::allocator<char>>>
|
||||
using request = message<true, Body, Headers>;
|
||||
/// A typical HTTP request
|
||||
template<class Body, class Fields = fields>
|
||||
using request = message<true, Body, Fields>;
|
||||
|
||||
/// A typical HTTP response message
|
||||
template<class Body,
|
||||
class Headers = basic_headers<std::allocator<char>>>
|
||||
using response = message<false, Body, Headers>;
|
||||
/// A typical HTTP response
|
||||
template<class Body, class Fields = fields>
|
||||
using response = message<false, Body, Fields>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Returns `true` if a HTTP/1 message indicates a keep alive.
|
||||
/** Returns `true` if the HTTP/1 message indicates a keep alive.
|
||||
|
||||
Undefined behavior if version is greater than 11.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
bool
|
||||
is_keep_alive(message<isRequest, Body, Headers> const& msg);
|
||||
is_keep_alive(header<isRequest, Fields> const& msg);
|
||||
|
||||
/** Returns `true` if a HTTP/1 message indicates an Upgrade request or response.
|
||||
/** Returns `true` if the HTTP/1 message indicates an Upgrade request or response.
|
||||
|
||||
Undefined behavior if version is greater than 11.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
bool
|
||||
is_upgrade(message<isRequest, Body, Headers> const& msg);
|
||||
is_upgrade(header<isRequest, Fields> const& msg);
|
||||
|
||||
/** HTTP/1 connection prepare options.
|
||||
|
||||
@@ -446,18 +449,18 @@ enum class connection
|
||||
/** Prepare a HTTP message.
|
||||
|
||||
This function will adjust the Content-Length, Transfer-Encoding,
|
||||
and Connection headers of the message based on the properties of
|
||||
and Connection fields 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 msg The message to prepare. The fields may be modified.
|
||||
|
||||
@param options A list of prepare options.
|
||||
*/
|
||||
template<
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class... Options>
|
||||
void
|
||||
prepare(message<isRequest, Body, Headers>& msg,
|
||||
prepare(message<isRequest, Body, Fields>& msg,
|
||||
Options&&... options);
|
||||
|
||||
} // http
|
||||
|
@@ -34,7 +34,7 @@ enum class parse_error
|
||||
invalid_ext_name,
|
||||
invalid_ext_val,
|
||||
|
||||
headers_too_big,
|
||||
header_too_big,
|
||||
body_too_big,
|
||||
short_read
|
||||
};
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#define BEAST_HTTP_PARSER_V1_HPP
|
||||
|
||||
#include <beast/http/concepts.hpp>
|
||||
#include <beast/http/headers_parser_v1.hpp>
|
||||
#include <beast/http/header_parser_v1.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/core/error.hpp>
|
||||
#include <beast/core/detail/type_traits.hpp>
|
||||
@@ -33,11 +33,11 @@ namespace http {
|
||||
For example, a 200 response to a CONNECT request from a tunneling
|
||||
proxy. In these cases, callers use the @ref skip_body option to
|
||||
inform the parser that no body is expected. The parser will consider
|
||||
the message complete after the all headers have been received.
|
||||
the message complete after the header has been received.
|
||||
|
||||
Example:
|
||||
@code
|
||||
parser_v1<true, empty_body, headers> p;
|
||||
parser_v1<true, empty_body, fields> p;
|
||||
p.set_option(skip_body{true});
|
||||
@endcode
|
||||
|
||||
@@ -61,10 +61,10 @@ struct skip_body
|
||||
|
||||
@note A new instance of the parser is required for each message.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
class parser_v1
|
||||
: public basic_parser_v1<isRequest,
|
||||
parser_v1<isRequest, Body, Headers>>
|
||||
parser_v1<isRequest, Body, Fields>>
|
||||
, private std::conditional<isRequest,
|
||||
detail::request_parser_base,
|
||||
detail::response_parser_base>::type
|
||||
@@ -72,7 +72,7 @@ class parser_v1
|
||||
public:
|
||||
/// The type of message this parser produces.
|
||||
using message_type =
|
||||
message<isRequest, Body, Headers>;
|
||||
message<isRequest, Body, Fields>;
|
||||
|
||||
private:
|
||||
using reader =
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
@param args Forwarded to the message constructor.
|
||||
|
||||
@note This function participates in overload resolution only
|
||||
if the first argument is not a parser or headers parser.
|
||||
if the first argument is not a parser or fields parser.
|
||||
*/
|
||||
#if GENERATING_DOCS
|
||||
template<class... Args>
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
class = typename std::enable_if<
|
||||
! std::is_same<typename
|
||||
std::decay<Arg1>::type,
|
||||
headers_parser_v1<isRequest, Headers>>::value &&
|
||||
header_parser_v1<isRequest, Fields>>::value &&
|
||||
! std::is_same<typename
|
||||
std::decay<Arg1>::type, parser_v1>::value
|
||||
>::type>
|
||||
@@ -136,20 +136,20 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Construct the parser from a headers parser.
|
||||
/** Construct the parser from a fields parser.
|
||||
|
||||
@param parser The headers parser to construct from.
|
||||
@param parser The fields parser to construct from.
|
||||
@param args Forwarded to the message body constructor.
|
||||
*/
|
||||
template<class... Args>
|
||||
explicit
|
||||
parser_v1(headers_parser_v1<isRequest, Headers>& parser,
|
||||
parser_v1(header_parser_v1<isRequest, Fields>& parser,
|
||||
Args&&... args)
|
||||
: m_(parser.release(), std::forward<Args>(args)...)
|
||||
{
|
||||
static_cast<basic_parser_v1<
|
||||
isRequest, parser_v1<
|
||||
isRequest, Body, Headers>>&>(*this) = parser;
|
||||
isRequest, Body, Fields>>&>(*this) = parser;
|
||||
}
|
||||
|
||||
/// Set the skip body option.
|
||||
@@ -185,7 +185,7 @@ public:
|
||||
valid if @ref complete would return `true`.
|
||||
|
||||
Requires:
|
||||
`message<isRequest, Body, Headers>` is @b MoveConstructible
|
||||
`message<isRequest, Body, Fields>` is @b MoveConstructible
|
||||
*/
|
||||
message_type
|
||||
release()
|
||||
@@ -204,7 +204,7 @@ private:
|
||||
return;
|
||||
flush_ = false;
|
||||
BOOST_ASSERT(! field_.empty());
|
||||
m_.headers.insert(field_, value_);
|
||||
m_.fields.insert(field_, value_);
|
||||
field_.clear();
|
||||
value_.clear();
|
||||
}
|
||||
@@ -265,7 +265,7 @@ private:
|
||||
}
|
||||
|
||||
void
|
||||
on_headers(std::uint64_t, error_code&)
|
||||
on_header(std::uint64_t, error_code&)
|
||||
{
|
||||
flush();
|
||||
m_.version = 10 * this->http_major() + this->http_minor();
|
||||
@@ -291,22 +291,22 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
/** Create a new parser from a headers parser.
|
||||
/** Create a new parser from a fields parser.
|
||||
|
||||
Associates a Body type with a headers parser, and returns
|
||||
Associates a Body type with a fields parser, and returns
|
||||
a new parser which parses a complete message object
|
||||
containing the original message headers and a new body
|
||||
containing the original message fields and a new body
|
||||
of the specified body type.
|
||||
|
||||
This function allows HTTP messages to be parsed in two stages.
|
||||
First, the headers are parsed and control is returned. Then,
|
||||
First, the fields are parsed and control is returned. Then,
|
||||
the caller can choose at run-time, the type of Body to
|
||||
associate with the message. And finally, complete the parse
|
||||
in a second call.
|
||||
|
||||
@param parser The headers parser to construct from. Ownership
|
||||
of the message headers in the headers parser is transferred
|
||||
as if by call to @ref headers_parser_v1::release.
|
||||
@param parser The fields parser to construct from. Ownership
|
||||
of the message fields in the fields parser is transferred
|
||||
as if by call to @ref header_parser_v1::release.
|
||||
|
||||
@param args Forwarded to the body constructor of the message
|
||||
in the new parser.
|
||||
@@ -315,19 +315,20 @@ private:
|
||||
|
||||
@par Example
|
||||
@code
|
||||
headers_parser<true, headers> ph;
|
||||
headers_parser<true, fields> ph;
|
||||
...
|
||||
auto p = with_body<string_body>(ph);
|
||||
...
|
||||
message<true, string_body, headers> m = p.release();
|
||||
message<true, string_body, fields> m = p.release();
|
||||
@endcode
|
||||
*/
|
||||
template<class Body, bool isRequest, class Headers, class... Args>
|
||||
parser_v1<isRequest, Body, Headers>
|
||||
with_body(headers_parser_v1<isRequest, Headers>& parser,
|
||||
template<class Body,
|
||||
bool isRequest, class Fields, class... Args>
|
||||
parser_v1<isRequest, Body, Fields>
|
||||
with_body(header_parser_v1<isRequest, Fields>& parser,
|
||||
Args&&... args)
|
||||
{
|
||||
return parser_v1<isRequest, Body, Headers>(
|
||||
return parser_v1<isRequest, Body, Fields>(
|
||||
parser, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
@@ -15,22 +15,27 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** Read HTTP/1 message headers from a stream.
|
||||
/** Read a HTTP/1 header from a stream.
|
||||
|
||||
This function is used to synchronously read message headers from
|
||||
the stream. The call blocks until one of the following conditions
|
||||
is true:
|
||||
This function is used to synchronously read a header
|
||||
from a stream. The call blocks until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li The complete message headers are read in.
|
||||
@li An entire header is read in.
|
||||
|
||||
@li An error occurs in the stream or parser.
|
||||
|
||||
This function is implemented in terms of one or more calls
|
||||
to the stream's `read_some` function. The implementation may
|
||||
read additional octets that lie past the end of the message
|
||||
headers being parsed. This additional data is stored in the
|
||||
fields being parsed. This additional data is stored in the
|
||||
stream buffer, which may be used in subsequent calls.
|
||||
|
||||
If the message corresponding to the header being received
|
||||
contains a message body, it is the callers responsibility
|
||||
to cause the body to be read in before attempting to read
|
||||
the next message.
|
||||
|
||||
@param stream The stream from which the data is to be read.
|
||||
The type must support the @b `SyncReadStream` concept.
|
||||
|
||||
@@ -40,37 +45,38 @@ namespace http {
|
||||
stream buffer's input sequence will be given to the parser
|
||||
first.
|
||||
|
||||
@param msg An object used to store the message headers.
|
||||
Any contents will be overwritten. The type must support
|
||||
copy assignment or move assignment.
|
||||
@param msg An object used to store the header. Any contents
|
||||
will be overwritten. The type must support copy assignment
|
||||
or move assignment.
|
||||
|
||||
@throws system_error Thrown on failure.
|
||||
*/
|
||||
template<class SyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Headers>
|
||||
bool isRequest, class Fields>
|
||||
void
|
||||
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message_headers<isRequest, Headers>& msg);
|
||||
header<isRequest, Fields>& msg);
|
||||
|
||||
/** Read HTTP/1 message headers from a stream.
|
||||
/** Read a HTTP/1 header from a stream.
|
||||
|
||||
This function is used to synchronously read message headers from
|
||||
the stream. The call blocks until one of the following conditions
|
||||
is true:
|
||||
This function is used to synchronously read a header
|
||||
from a stream. The call blocks until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li The complete message headers are read in.
|
||||
@li An entire header is read in.
|
||||
|
||||
@li An error occurs in the stream or parser.
|
||||
|
||||
This function is implemented in terms of one or more calls
|
||||
to the stream's `read_some` function. The implementation may
|
||||
read additional octets that lie past the end of the message
|
||||
headers being parsed. This additional data is stored in the
|
||||
fields being parsed. This additional data is stored in the
|
||||
stream buffer, which may be used in subsequent calls.
|
||||
|
||||
If the message being received contains a message body, it
|
||||
is the callers responsibility to cause the body to be read
|
||||
in before attempting to read the next message.
|
||||
If the message corresponding to the header being received
|
||||
contains a message body, it is the callers responsibility
|
||||
to cause the body to be read in before attempting to read
|
||||
the next message.
|
||||
|
||||
@param stream The stream from which the data is to be read.
|
||||
The type must support the @b `SyncReadStream` concept.
|
||||
@@ -81,40 +87,42 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
stream buffer's input sequence will be given to the parser
|
||||
first.
|
||||
|
||||
@param msg An object used to store the message headers.
|
||||
Any contents will be overwritten. The type must support
|
||||
copy assignment or move assignment.
|
||||
@param msg An object used to store the header. Any contents
|
||||
will be overwritten. The type must support copy assignment
|
||||
or move assignment.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
template<class SyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Headers>
|
||||
bool isRequest, class Fields>
|
||||
void
|
||||
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message_headers<isRequest, Headers>& msg,
|
||||
header<isRequest, Fields>& msg,
|
||||
error_code& ec);
|
||||
|
||||
/** Start an asynchronous operation to read HTTP/1 message headers from a stream.
|
||||
/** Read a HTTP/1 header asynchronously from a stream.
|
||||
|
||||
This function is used to asynchronously read a message from the
|
||||
stream. The function call always returns immediately. The asynchronous
|
||||
operation will continue until one of the following conditions is true:
|
||||
This function is used to asynchronously read a header from
|
||||
a stream. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li A complete message is read in.
|
||||
@li An entire header is read in.
|
||||
|
||||
@li An error occurs in the stream or parser.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_read_some` function, and is known as a
|
||||
the stream's `async_read_some` function, and is known as a
|
||||
<em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other operations until this operation completes.
|
||||
The implementation may read additional octets that lie past the
|
||||
end of the message headers being parsed. This additional data is
|
||||
end of the message fields being parsed. This additional data is
|
||||
stored in the stream buffer, which may be used in subsequent calls.
|
||||
|
||||
If the message being received contains a message body, it
|
||||
is the callers responsibility to cause the body to be read
|
||||
in before attempting to read the next message.
|
||||
If the message corresponding to the header being received
|
||||
contains a message body, it is the callers responsibility
|
||||
to cause the body to be read in before attempting to read
|
||||
the next message.
|
||||
|
||||
@param stream The stream to read the message from.
|
||||
The type must support the @b `AsyncReadStream` concept.
|
||||
@@ -125,13 +133,14 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
stream buffer's input sequence will be given to the parser
|
||||
first.
|
||||
|
||||
@param msg An object used to store the message. Any contents
|
||||
@param msg An object used to store the header. Any contents
|
||||
will be overwritten. The type must support copy assignment or
|
||||
move assignment.
|
||||
move assignment. The object must remain valid at least until
|
||||
the completion handler is called; ownership is not transferred.
|
||||
|
||||
@param handler The handler to be called when the request completes.
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
function signature of the handler must be:
|
||||
@param handler The handler to be called when the operation
|
||||
completes. Copies will be made of the handler as required.
|
||||
The equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& error // result of operation
|
||||
); @endcode
|
||||
@@ -141,7 +150,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class AsyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class ReadHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
@@ -150,13 +159,13 @@ typename async_completion<
|
||||
ReadHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message_headers<isRequest, Headers>& msg,
|
||||
header<isRequest, Fields>& msg,
|
||||
ReadHandler&& handler);
|
||||
|
||||
/** Read a HTTP/1 message from a stream.
|
||||
|
||||
This function is used to synchronously read a message from
|
||||
the stream. The call blocks until one of the following conditions
|
||||
a stream. The call blocks until one of the following conditions
|
||||
is true:
|
||||
|
||||
@li A complete message is read in.
|
||||
@@ -185,15 +194,15 @@ async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
@throws system_error Thrown on failure.
|
||||
*/
|
||||
template<class SyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
void
|
||||
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message<isRequest, Body, Headers>& msg);
|
||||
message<isRequest, Body, Fields>& msg);
|
||||
|
||||
/** Read a HTTP/1 message from a stream.
|
||||
|
||||
This function is used to synchronously read a message from
|
||||
the stream. The call blocks until one of the following conditions
|
||||
a stream. The call blocks until one of the following conditions
|
||||
is true:
|
||||
|
||||
@li A complete message is read in.
|
||||
@@ -222,24 +231,25 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
template<class SyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
void
|
||||
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message<isRequest, Body, Headers>& msg,
|
||||
message<isRequest, Body, Fields>& msg,
|
||||
error_code& ec);
|
||||
|
||||
/** Start an asynchronous operation to read a HTTP/1 message from a stream.
|
||||
/** Read a HTTP/1 message asynchronously from a stream.
|
||||
|
||||
This function is used to asynchronously read a message from the
|
||||
stream. The function call always returns immediately. The asynchronous
|
||||
operation will continue until one of the following conditions is true:
|
||||
This function is used to asynchronously read a message from
|
||||
a stream. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li A complete message is read in.
|
||||
|
||||
@li An error occurs in the stream or parser.
|
||||
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the next layer's `async_read_some` function, and is known as a
|
||||
the stream's `async_read_some` function, and is known as a
|
||||
<em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other operations until this operation completes.
|
||||
The implementation may read additional octets that lie past the
|
||||
@@ -255,13 +265,14 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
stream buffer's input sequence will be given to the parser
|
||||
first.
|
||||
|
||||
@param msg An object used to store the message. Any contents
|
||||
@param msg An object used to store the header. Any contents
|
||||
will be overwritten. The type must support copy assignment or
|
||||
move assignment.
|
||||
move assignment. The object must remain valid at least until
|
||||
the completion handler is called; ownership is not transferred.
|
||||
|
||||
@param handler The handler to be called when the request completes.
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
function signature of the handler must be:
|
||||
@param handler The handler to be called when the operation
|
||||
completes. Copies will be made of the handler as required.
|
||||
The equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& error // result of operation
|
||||
); @endcode
|
||||
@@ -271,7 +282,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class AsyncReadStream, class DynamicBuffer,
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class ReadHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
@@ -280,7 +291,7 @@ typename async_completion<
|
||||
ReadHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||
message<isRequest, Body, Headers>& msg,
|
||||
message<isRequest, Body, Fields>& msg,
|
||||
ReadHandler&& handler);
|
||||
|
||||
} // http
|
||||
|
@@ -11,7 +11,8 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** Returns the text for a known status code integer. */
|
||||
namespace detail {
|
||||
|
||||
template<class = void>
|
||||
char const*
|
||||
reason_string(int status)
|
||||
@@ -66,6 +67,16 @@ reason_string(int status)
|
||||
return "<unknown-status>";
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
/** Returns the text for a known status code integer. */
|
||||
inline
|
||||
char const*
|
||||
reason_string(int status)
|
||||
{
|
||||
return detail::reason_string(status);
|
||||
}
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
|
@@ -8,9 +8,12 @@
|
||||
#ifndef BEAST_HTTP_STRING_BODY_HPP
|
||||
#define BEAST_HTTP_STRING_BODY_HPP
|
||||
|
||||
#include <beast/http/body_type.hpp>
|
||||
#include <beast/core/error.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <beast/core/detail/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -35,10 +38,10 @@ private:
|
||||
value_type& s_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
string_body, Headers>& m) noexcept
|
||||
string_body, Fields>& m) noexcept
|
||||
: s_(m.body)
|
||||
{
|
||||
}
|
||||
@@ -63,10 +66,10 @@ private:
|
||||
value_type const& body_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
explicit
|
||||
writer(message<
|
||||
isRequest, string_body, Headers> const& msg) noexcept
|
||||
isRequest, string_body, Fields> const& msg) noexcept
|
||||
: body_(msg.body)
|
||||
{
|
||||
}
|
||||
|
@@ -17,94 +17,98 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** Write HTTP/1 message headers on a stream.
|
||||
/** Write a HTTP/1 header to a stream.
|
||||
|
||||
This function is used to write message headers to a stream. The
|
||||
call will block until one of the following conditions is true:
|
||||
This function is used to synchronously write a header to
|
||||
a stream. The call will block until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li All the message headers are sent.
|
||||
@li The entire header is written.
|
||||
|
||||
@li An error occurs.
|
||||
|
||||
This operation is implemented in terms of one or more calls
|
||||
to the stream's `write_some` function.
|
||||
|
||||
Regardless of the semantic meaning of the headers (for example,
|
||||
specifying a zero-length message body and Connection: Close),
|
||||
Regardless of the semantic meaning of the header (for example,
|
||||
specifying "Content-Length: 0" and "Connection: close"),
|
||||
this function will not return `boost::asio::error::eof`.
|
||||
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b `SyncWriteStream` concept.
|
||||
|
||||
@param msg The message headers to write.
|
||||
@param msg The header to write.
|
||||
|
||||
@throws system_error Thrown on failure.
|
||||
*/
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Headers>
|
||||
bool isRequest, class Fields>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message_headers<isRequest, Headers> const& msg);
|
||||
header<isRequest, Fields> const& msg);
|
||||
|
||||
/** Write HTTP/1 message headers on a stream.
|
||||
/** Write a HTTP/1 header to a stream.
|
||||
|
||||
This function is used to write message headers to a stream. The
|
||||
call will block until one of the following conditions is true:
|
||||
This function is used to synchronously write a header to
|
||||
a stream. The call will block until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li All the message headers are sent.
|
||||
@li The entire header is written.
|
||||
|
||||
@li An error occurs.
|
||||
|
||||
This operation is implemented in terms of one or more calls
|
||||
to the stream's `write_some` function.
|
||||
|
||||
Regardless of the semantic meaning of the headers (for example,
|
||||
specifying a zero-length message body and Connection: Close),
|
||||
Regardless of the semantic meaning of the header (for example,
|
||||
specifying "Content-Length: 0" and "Connection: close"),
|
||||
this function will not return `boost::asio::error::eof`.
|
||||
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b `SyncWriteStream` concept.
|
||||
|
||||
@param msg The message headers to write.
|
||||
@param msg The header to write.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Headers>
|
||||
bool isRequest, class Fields>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message_headers<isRequest, Headers> const& msg,
|
||||
header<isRequest, Fields> const& msg,
|
||||
error_code& ec);
|
||||
|
||||
/** Start an asynchronous operation to write HTTP/1 message headers to a stream.
|
||||
/** Write a HTTP/1 header asynchronously to a stream.
|
||||
|
||||
This function is used to asynchronously write message headers to a stream.
|
||||
The function call always returns immediately. The asynchronous
|
||||
operation will continue until one of the following conditions is true:
|
||||
This function is used to asynchronously write a header to
|
||||
a stream. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li The entire message headers are sent.
|
||||
@li The entire header is written.
|
||||
|
||||
@li An error occurs.
|
||||
|
||||
This operation is implemented in terms of one or more calls to the
|
||||
stream's `async_write_some` functions, and is known as a <em>composed
|
||||
operation</em>. The program must ensure that the stream performs no
|
||||
other write operations (such as @ref async_write, the stream's
|
||||
`async_write_some` function, or any other composed operations that
|
||||
perform writes) until this operation completes.
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the stream's `async_write_some` functions, and is known as a
|
||||
<em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other write operations until this operation
|
||||
completes.
|
||||
|
||||
Regardless of the semantic meaning of the headers (for example,
|
||||
specifying a zero-length message body and Connection: Close),
|
||||
the handler will not be called with `boost::asio::error::eof`.
|
||||
Regardless of the semantic meaning of the header (for example,
|
||||
specifying "Content-Length: 0" and "Connection: close"),
|
||||
this function will not return `boost::asio::error::eof`.
|
||||
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b `AsyncWriteStream` concept.
|
||||
|
||||
@param msg The message headers to send.
|
||||
@param msg The header to write. The object must remain valid
|
||||
at least until the completion handler is called; ownership is
|
||||
not transferred.
|
||||
|
||||
@param handler The handler to be called when the request completes.
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
function signature of the handler must be:
|
||||
@param handler The handler to be called when the operation
|
||||
completes. Copies will be made of the handler as required.
|
||||
The equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& error // result of operation
|
||||
); @endcode
|
||||
@@ -112,12 +116,9 @@ write(SyncWriteStream& stream,
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
|
||||
@note The message object must remain valid at least until the
|
||||
completion handler is called, no copies are made.
|
||||
*/
|
||||
template<class AsyncWriteStream,
|
||||
bool isRequest, class Headers,
|
||||
bool isRequest, class Fields,
|
||||
class WriteHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
@@ -126,17 +127,17 @@ typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_write(AsyncWriteStream& stream,
|
||||
message_headers<isRequest, Headers> const& msg,
|
||||
header<isRequest, Fields> const& msg,
|
||||
WriteHandler&& handler);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Write a HTTP/1 message on a stream.
|
||||
/** Write a HTTP/1 message to a stream.
|
||||
|
||||
This function is used to write a message to a stream. The call
|
||||
will block until one of the following conditions is true:
|
||||
|
||||
@li The entire message is sent.
|
||||
@li The entire message is written.
|
||||
|
||||
@li An error occurs.
|
||||
|
||||
@@ -157,17 +158,17 @@ async_write(AsyncWriteStream& stream,
|
||||
@throws system_error Thrown on failure.
|
||||
*/
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg);
|
||||
message<isRequest, Body, Fields> const& msg);
|
||||
|
||||
/** Write a HTTP/1 message on a stream.
|
||||
|
||||
This function is used to write a message to a stream. The call
|
||||
will block until one of the following conditions is true:
|
||||
|
||||
@li The entire message is sent.
|
||||
@li The entire message is written.
|
||||
|
||||
@li An error occurs.
|
||||
|
||||
@@ -188,28 +189,28 @@ write(SyncWriteStream& stream,
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Body, class Headers>
|
||||
bool isRequest, class Body, class Fields>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message<isRequest, Body, Fields> const& msg,
|
||||
error_code& ec);
|
||||
|
||||
/** Start an asynchronous operation to write a HTTP/1 message to a stream.
|
||||
/** Write a HTTP/1 message asynchronously to a stream.
|
||||
|
||||
This function is used to asynchronously write a message to a stream.
|
||||
The function call always returns immediately. The asynchronous
|
||||
operation will continue until one of the following conditions is true:
|
||||
This function is used to asynchronously write a message to
|
||||
a stream. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
conditions is true:
|
||||
|
||||
@li The entire message is sent.
|
||||
@li The entire message is written.
|
||||
|
||||
@li An error occurs.
|
||||
|
||||
This operation is implemented in terms of one or more calls to the
|
||||
stream's `async_write_some` functions, and is known as a <em>composed
|
||||
operation</em>. The program must ensure that the stream performs no
|
||||
other write operations (such as @ref async_write, the stream's
|
||||
`async_write_some` function, or any other composed operations that
|
||||
perform writes) until this operation completes.
|
||||
This operation is implemented in terms of one or more calls to
|
||||
the stream's `async_write_some` functions, and is known as a
|
||||
<em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other write operations until this operation
|
||||
completes.
|
||||
|
||||
The implementation will automatically perform chunk encoding if
|
||||
the contents of the message indicate that chunk encoding is required.
|
||||
@@ -220,11 +221,13 @@ write(SyncWriteStream& stream,
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b `AsyncWriteStream` concept.
|
||||
|
||||
@param msg The message to send.
|
||||
@param msg The message to write. The object must remain valid
|
||||
at least until the completion handler is called; ownership is
|
||||
not transferred.
|
||||
|
||||
@param handler The handler to be called when the request completes.
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
function signature of the handler must be:
|
||||
@param handler The handler to be called when the operation
|
||||
completes. Copies will be made of the handler as required.
|
||||
The equivalent function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& error // result of operation
|
||||
); @endcode
|
||||
@@ -232,12 +235,9 @@ write(SyncWriteStream& stream,
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
|
||||
@note The message object must remain valid at least until the
|
||||
completion handler is called, no copies are made.
|
||||
*/
|
||||
template<class AsyncWriteStream,
|
||||
bool isRequest, class Body, class Headers,
|
||||
bool isRequest, class Body, class Fields,
|
||||
class WriteHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
@@ -246,25 +246,24 @@ typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_write(AsyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message<isRequest, Body, Fields> const& msg,
|
||||
WriteHandler&& handler);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Serialize HTTP/1 message headers to a `std::ostream`.
|
||||
/** Serialize a HTTP/1 header to a `std::ostream`.
|
||||
|
||||
The function converts the message headers to its HTTP/1
|
||||
serialized representation and stores the result in the output
|
||||
stream.
|
||||
The function converts the header to its HTTP/1 serialized
|
||||
representation and stores the result in the output stream.
|
||||
|
||||
@param os The output stream to write to.
|
||||
|
||||
@param msg The message headers to write.
|
||||
@param msg The message fields to write.
|
||||
*/
|
||||
template<bool isRequest, class Headers>
|
||||
template<bool isRequest, class Fields>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message_headers<isRequest, Headers> const& msg);
|
||||
header<isRequest, Fields> const& msg);
|
||||
|
||||
/** Serialize a HTTP/1 message to a `std::ostream`.
|
||||
|
||||
@@ -278,10 +277,10 @@ operator<<(std::ostream& os,
|
||||
|
||||
@param msg The message to write.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message<isRequest, Body, Headers> const& msg);
|
||||
message<isRequest, Body, Fields> const& msg);
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
@@ -102,7 +102,7 @@ private:
|
||||
void
|
||||
operator()(request_type& req, std::false_type)
|
||||
{
|
||||
req.headers.replace("User-Agent",
|
||||
req.fields.replace("User-Agent",
|
||||
std::string{"Beast/"} + BEAST_VERSION_STRING);
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
void
|
||||
operator()(response_type& res, std::false_type)
|
||||
{
|
||||
res.headers.replace("Server",
|
||||
res.fields.replace("Server",
|
||||
std::string{"Beast/"} + BEAST_VERSION_STRING);
|
||||
}
|
||||
};
|
||||
|
@@ -43,9 +43,9 @@ class stream<NextLayer>::response_op
|
||||
int state = 0;
|
||||
|
||||
template<class DeducedHandler,
|
||||
class Body, class Headers>
|
||||
class Body, class Fields>
|
||||
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
||||
http::request<Body, Headers> const& req,
|
||||
http::request<Body, Fields> const& req,
|
||||
bool cont_)
|
||||
: ws(ws_)
|
||||
, resp(ws_.build_response(req))
|
||||
@@ -305,11 +305,11 @@ async_accept(ConstBufferSequence const& bs, AcceptHandler&& handler)
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Headers, class AcceptHandler>
|
||||
template<class Body, class Fields, class AcceptHandler>
|
||||
typename async_completion<
|
||||
AcceptHandler, void(error_code)>::result_type
|
||||
stream<NextLayer>::
|
||||
async_accept(http::request<Body, Headers> const& req,
|
||||
async_accept(http::request<Body, Fields> const& req,
|
||||
AcceptHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
@@ -390,10 +390,10 @@ accept(ConstBufferSequence const& buffers, error_code& ec)
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept(http::request<Body, Headers> const& request)
|
||||
accept(http::request<Body, Fields> const& request)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
@@ -404,10 +404,10 @@ accept(http::request<Body, Headers> const& request)
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept(http::request<Body, Headers> const& req,
|
||||
accept(http::request<Body, Fields> const& req,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
|
@@ -66,21 +66,21 @@ build_request(boost::string_ref const& host,
|
||||
req.url = { resource.data(), resource.size() };
|
||||
req.version = 11;
|
||||
req.method = "GET";
|
||||
req.headers.insert("Host", host);
|
||||
req.headers.insert("Upgrade", "websocket");
|
||||
req.fields.insert("Host", host);
|
||||
req.fields.insert("Upgrade", "websocket");
|
||||
key = detail::make_sec_ws_key(maskgen_);
|
||||
req.headers.insert("Sec-WebSocket-Key", key);
|
||||
req.headers.insert("Sec-WebSocket-Version", "13");
|
||||
req.fields.insert("Sec-WebSocket-Key", key);
|
||||
req.fields.insert("Sec-WebSocket-Version", "13");
|
||||
(*d_)(req);
|
||||
http::prepare(req, http::connection::upgrade);
|
||||
return req;
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
http::response<http::string_body>
|
||||
stream<NextLayer>::
|
||||
build_response(http::request<Body, Headers> const& req)
|
||||
build_response(http::request<Body, Fields> const& req)
|
||||
{
|
||||
auto err =
|
||||
[&](std::string const& text)
|
||||
@@ -103,15 +103,15 @@ build_response(http::request<Body, Headers> const& req)
|
||||
return err("Wrong method");
|
||||
if(! is_upgrade(req))
|
||||
return err("Expected Upgrade request");
|
||||
if(! req.headers.exists("Host"))
|
||||
if(! req.fields.exists("Host"))
|
||||
return err("Missing Host");
|
||||
if(! req.headers.exists("Sec-WebSocket-Key"))
|
||||
if(! req.fields.exists("Sec-WebSocket-Key"))
|
||||
return err("Missing Sec-WebSocket-Key");
|
||||
if(! http::token_list{req.headers["Upgrade"]}.exists("websocket"))
|
||||
if(! http::token_list{req.fields["Upgrade"]}.exists("websocket"))
|
||||
return err("Missing websocket Upgrade token");
|
||||
{
|
||||
auto const version =
|
||||
req.headers["Sec-WebSocket-Version"];
|
||||
req.fields["Sec-WebSocket-Version"];
|
||||
if(version.empty())
|
||||
return err("Missing Sec-WebSocket-Version");
|
||||
if(version != "13")
|
||||
@@ -120,7 +120,7 @@ build_response(http::request<Body, Headers> const& req)
|
||||
res.status = 426;
|
||||
res.reason = http::reason_string(res.status);
|
||||
res.version = req.version;
|
||||
res.headers.insert("Sec-WebSocket-Version", "13");
|
||||
res.fields.insert("Sec-WebSocket-Version", "13");
|
||||
prepare(res,
|
||||
(is_keep_alive(req) && keep_alive_) ?
|
||||
http::connection::keep_alive :
|
||||
@@ -132,24 +132,24 @@ build_response(http::request<Body, Headers> const& req)
|
||||
res.status = 101;
|
||||
res.reason = http::reason_string(res.status);
|
||||
res.version = req.version;
|
||||
res.headers.insert("Upgrade", "websocket");
|
||||
res.fields.insert("Upgrade", "websocket");
|
||||
{
|
||||
auto const key =
|
||||
req.headers["Sec-WebSocket-Key"];
|
||||
res.headers.insert("Sec-WebSocket-Accept",
|
||||
req.fields["Sec-WebSocket-Key"];
|
||||
res.fields.insert("Sec-WebSocket-Accept",
|
||||
detail::make_sec_ws_accept(key));
|
||||
}
|
||||
res.headers.replace("Server", "Beast.WSProto");
|
||||
res.fields.replace("Server", "Beast.WSProto");
|
||||
(*d_)(res);
|
||||
http::prepare(res, http::connection::upgrade);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
do_response(http::response<Body, Headers> const& res,
|
||||
do_response(http::response<Body, Fields> const& res,
|
||||
boost::string_ref const& key, error_code& ec)
|
||||
{
|
||||
// VFALCO Review these error codes
|
||||
@@ -160,11 +160,11 @@ do_response(http::response<Body, Headers> const& res,
|
||||
return fail();
|
||||
if(! is_upgrade(res))
|
||||
return fail();
|
||||
if(! http::token_list{res.headers["Upgrade"]}.exists("websocket"))
|
||||
if(! http::token_list{res.fields["Upgrade"]}.exists("websocket"))
|
||||
return fail();
|
||||
if(! res.headers.exists("Sec-WebSocket-Accept"))
|
||||
if(! res.fields.exists("Sec-WebSocket-Accept"))
|
||||
return fail();
|
||||
if(res.headers["Sec-WebSocket-Accept"] !=
|
||||
if(res.fields["Sec-WebSocket-Accept"] !=
|
||||
detail::make_sec_ws_accept(key))
|
||||
return fail();
|
||||
open(detail::role_type::client);
|
||||
|
@@ -86,14 +86,14 @@ struct auto_fragment
|
||||
@code
|
||||
struct identity
|
||||
{
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void
|
||||
operator()(http::message<isRequest, Body, Headers>& m)
|
||||
operator()(http::message<isRequest, Body, Fields>& m)
|
||||
{
|
||||
if(isRequest)
|
||||
m.headers.replace("User-Agent", "MyClient");
|
||||
m.fields.replace("User-Agent", "MyClient");
|
||||
else
|
||||
m.headers.replace("Server", "MyServer");
|
||||
m.fields.replace("Server", "MyServer");
|
||||
}
|
||||
};
|
||||
...
|
||||
@@ -284,7 +284,7 @@ struct read_buffer_size
|
||||
/** Maximum incoming message size option.
|
||||
|
||||
Sets the largest permissible incoming message size. Message
|
||||
frame headers indicating a size that would bring the total
|
||||
frame fields indicating a size that would bring the total
|
||||
message size over this limit will cause a protocol failure.
|
||||
|
||||
The default setting is 16 megabytes. A value of zero indicates
|
||||
|
@@ -583,9 +583,9 @@ public:
|
||||
@throws system_error Thrown on failure.
|
||||
*/
|
||||
// VFALCO TODO This should also take a DynamicBuffer with any leftover bytes.
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
accept(http::request<Body, Headers> const& request);
|
||||
accept(http::request<Body, Fields> const& request);
|
||||
|
||||
/** Respond to a WebSocket HTTP Upgrade request
|
||||
|
||||
@@ -615,9 +615,9 @@ public:
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
accept(http::request<Body, Headers> const& request,
|
||||
accept(http::request<Body, Fields> const& request,
|
||||
error_code& ec);
|
||||
|
||||
/** Start responding to a WebSocket HTTP Upgrade request.
|
||||
@@ -661,14 +661,14 @@ public:
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class Body, class Headers, class AcceptHandler>
|
||||
template<class Body, class Fields, class AcceptHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
#else
|
||||
typename async_completion<
|
||||
AcceptHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_accept(http::request<Body, Headers> const& request,
|
||||
async_accept(http::request<Body, Fields> const& request,
|
||||
AcceptHandler&& handler);
|
||||
|
||||
/** Send a HTTP WebSocket Upgrade request and receive the response.
|
||||
@@ -1627,13 +1627,13 @@ private:
|
||||
boost::string_ref const& resource,
|
||||
std::string& key);
|
||||
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
http::response<http::string_body>
|
||||
build_response(http::request<Body, Headers> const& req);
|
||||
build_response(http::request<Body, Fields> const& req);
|
||||
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
do_response(http::response<Body, Headers> const& resp,
|
||||
do_response(http::response<Body, Fields> const& resp,
|
||||
boost::string_ref const& key, error_code& ec);
|
||||
|
||||
void
|
||||
|
@@ -43,13 +43,12 @@ unit-test core-tests :
|
||||
unit-test http-tests :
|
||||
../extras/beast/unit_test/main.cpp
|
||||
http/basic_dynabuf_body.cpp
|
||||
http/basic_headers.cpp
|
||||
http/basic_fields.cpp
|
||||
http/basic_parser_v1.cpp
|
||||
http/body_type.cpp
|
||||
http/concepts.cpp
|
||||
http/empty_body.cpp
|
||||
http/headers.cpp
|
||||
http/headers_parser_v1.cpp
|
||||
http/fields.cpp
|
||||
http/header_parser_v1.cpp
|
||||
http/message.cpp
|
||||
http/parse.cpp
|
||||
http/parse_error.cpp
|
||||
|
@@ -11,13 +11,12 @@ add_executable (http-tests
|
||||
fail_parser.hpp
|
||||
../../extras/beast/unit_test/main.cpp
|
||||
basic_dynabuf_body.cpp
|
||||
basic_headers.cpp
|
||||
basic_fields.cpp
|
||||
basic_parser_v1.cpp
|
||||
body_type.cpp
|
||||
concepts.cpp
|
||||
empty_body.cpp
|
||||
headers.cpp
|
||||
headers_parser_v1.cpp
|
||||
fields.cpp
|
||||
header_parser_v1.cpp
|
||||
message.cpp
|
||||
parse.cpp
|
||||
parse_error.cpp
|
||||
|
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/basic_headers.hpp>
|
||||
#include <beast/http/basic_fields.hpp>
|
||||
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
@@ -14,18 +14,18 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class basic_headers_test : public beast::unit_test::suite
|
||||
class basic_fields_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class Allocator>
|
||||
using bha = basic_headers<Allocator>;
|
||||
using bha = basic_fields<Allocator>;
|
||||
|
||||
using bh = basic_headers<std::allocator<char>>;
|
||||
using bh = basic_fields<std::allocator<char>>;
|
||||
|
||||
template<class Allocator>
|
||||
static
|
||||
void
|
||||
fill(std::size_t n, basic_headers<Allocator>& h)
|
||||
fill(std::size_t n, basic_fields<Allocator>& h)
|
||||
{
|
||||
for(std::size_t i = 1; i<= n; ++i)
|
||||
h.insert(boost::lexical_cast<std::string>(i), i);
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(basic_headers,http,beast);
|
||||
BEAST_DEFINE_TESTSUITE(basic_fields,http,beast);
|
||||
|
||||
} // http
|
||||
} // beast
|
@@ -51,7 +51,7 @@ public:
|
||||
bool start = false;
|
||||
bool field = false;
|
||||
bool value = false;
|
||||
bool headers = false;
|
||||
bool fields = false;
|
||||
bool _body_what = false;
|
||||
bool body = false;
|
||||
bool complete = false;
|
||||
@@ -92,9 +92,9 @@ public:
|
||||
value = true;
|
||||
}
|
||||
void
|
||||
on_headers(std::uint64_t, error_code&)
|
||||
on_header(std::uint64_t, error_code&)
|
||||
{
|
||||
headers = true;
|
||||
fields = true;
|
||||
}
|
||||
body_what
|
||||
on_body_what(std::uint64_t, error_code&)
|
||||
@@ -135,7 +135,7 @@ public:
|
||||
BEAST_EXPECT(p.request);
|
||||
BEAST_EXPECT(p.field);
|
||||
BEAST_EXPECT(p.value);
|
||||
BEAST_EXPECT(p.headers);
|
||||
BEAST_EXPECT(p.fields);
|
||||
BEAST_EXPECT(p._body_what);
|
||||
BEAST_EXPECT(p.body);
|
||||
BEAST_EXPECT(p.complete);
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
BEAST_EXPECT(p.response);
|
||||
BEAST_EXPECT(p.field);
|
||||
BEAST_EXPECT(p.value);
|
||||
BEAST_EXPECT(p.headers);
|
||||
BEAST_EXPECT(p.fields);
|
||||
BEAST_EXPECT(p.body);
|
||||
BEAST_EXPECT(p.complete);
|
||||
}
|
||||
@@ -1104,7 +1104,7 @@ public:
|
||||
{
|
||||
test::fail_counter fc(1000);
|
||||
fail_parser<true> p(fc);
|
||||
p.set_option(headers_max_size{n});
|
||||
p.set_option(header_max_size{n});
|
||||
error_code ec;
|
||||
p.write(buf(
|
||||
"GET / HTTP/1.1\r\n"
|
||||
@@ -1113,7 +1113,7 @@ public:
|
||||
), ec);
|
||||
if(! ec)
|
||||
break;
|
||||
BEAST_EXPECT(ec == parse_error::headers_too_big);
|
||||
BEAST_EXPECT(ec == parse_error::header_too_big);
|
||||
}
|
||||
BEAST_EXPECT(n < Limit);
|
||||
}
|
||||
@@ -1122,7 +1122,7 @@ public:
|
||||
{
|
||||
test::fail_counter fc(1000);
|
||||
fail_parser<false> p(fc);
|
||||
p.set_option(headers_max_size{n});
|
||||
p.set_option(header_max_size{n});
|
||||
error_code ec;
|
||||
p.write(buf(
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
@@ -1133,7 +1133,7 @@ public:
|
||||
), ec);
|
||||
if(! ec)
|
||||
break;
|
||||
BEAST_EXPECT(ec == parse_error::headers_too_big);
|
||||
BEAST_EXPECT(ec == parse_error::header_too_big);
|
||||
}
|
||||
BEAST_EXPECT(n < Limit);
|
||||
}
|
||||
|
@@ -1,9 +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/body_type.hpp>
|
@@ -86,7 +86,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
on_headers(std::uint64_t content_length, error_code& ec)
|
||||
on_header(std::uint64_t content_length, error_code& ec)
|
||||
{
|
||||
if(fc_.fail(ec))
|
||||
return;
|
||||
|
@@ -6,4 +6,4 @@
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/fields.hpp>
|
@@ -6,23 +6,23 @@
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/headers_parser_v1.hpp>
|
||||
#include <beast/http/header_parser_v1.hpp>
|
||||
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/fields.hpp>
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class headers_parser_v1_test : public beast::unit_test::suite
|
||||
class header_parser_v1_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void testParser()
|
||||
{
|
||||
{
|
||||
error_code ec;
|
||||
headers_parser_v1<true, headers> p;
|
||||
header_parser_v1<true, fields> p;
|
||||
BEAST_EXPECT(! p.complete());
|
||||
auto const n = p.write(boost::asio::buffer(
|
||||
"GET / HTTP/1.1\r\n"
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
}
|
||||
{
|
||||
error_code ec;
|
||||
headers_parser_v1<true, headers> p;
|
||||
header_parser_v1<true, fields> p;
|
||||
BEAST_EXPECT(! p.complete());
|
||||
auto const n = p.write(boost::asio::buffer(
|
||||
"GET / HTTP/1.1\r\n"
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
}
|
||||
{
|
||||
error_code ec;
|
||||
headers_parser_v1<false, headers> p;
|
||||
header_parser_v1<false, fields> p;
|
||||
BEAST_EXPECT(! p.complete());
|
||||
auto const n = p.write(boost::asio::buffer(
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
}
|
||||
{
|
||||
error_code ec;
|
||||
headers_parser_v1<false, headers> p;
|
||||
header_parser_v1<false, fields> p;
|
||||
BEAST_EXPECT(! p.complete());
|
||||
auto const n = p.write(boost::asio::buffer(
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(headers_parser_v1,http,beast);
|
||||
BEAST_DEFINE_TESTSUITE(header_parser_v1,http,beast);
|
||||
|
||||
} // http
|
||||
} // beast
|
@@ -9,7 +9,7 @@
|
||||
#include <beast/http/message.hpp>
|
||||
|
||||
#include <beast/http/empty_body.hpp>
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/fields.hpp>
|
||||
#include <beast/http/string_body.hpp>
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <type_traits>
|
||||
@@ -73,66 +73,66 @@ public:
|
||||
void testMessage()
|
||||
{
|
||||
static_assert(std::is_constructible<
|
||||
message<true, default_body, headers>>::value, "");
|
||||
message<true, default_body, fields>>::value, "");
|
||||
|
||||
static_assert(std::is_constructible<
|
||||
message<true, one_arg_body, headers>, Arg1>::value, "");
|
||||
message<true, one_arg_body, fields>, Arg1>::value, "");
|
||||
|
||||
static_assert(std::is_constructible<
|
||||
message<true, one_arg_body, headers>, Arg1 const>::value, "");
|
||||
message<true, one_arg_body, fields>, Arg1 const>::value, "");
|
||||
|
||||
static_assert(std::is_constructible<
|
||||
message<true, one_arg_body, headers>, Arg1 const&>::value, "");
|
||||
message<true, one_arg_body, fields>, Arg1 const&>::value, "");
|
||||
|
||||
static_assert(std::is_constructible<
|
||||
message<true, one_arg_body, headers>, Arg1&&>::value, "");
|
||||
message<true, one_arg_body, fields>, Arg1&&>::value, "");
|
||||
|
||||
static_assert(! std::is_constructible<
|
||||
message<true, one_arg_body, headers>>::value, "");
|
||||
message<true, one_arg_body, fields>>::value, "");
|
||||
|
||||
static_assert(std::is_constructible<
|
||||
message<true, one_arg_body, headers>,
|
||||
Arg1, headers::allocator_type>::value, "");
|
||||
message<true, one_arg_body, fields>,
|
||||
Arg1, fields::allocator_type>::value, "");
|
||||
|
||||
static_assert(std::is_constructible<
|
||||
message<true, one_arg_body, headers>, std::piecewise_construct_t,
|
||||
message<true, one_arg_body, fields>, std::piecewise_construct_t,
|
||||
std::tuple<Arg1>>::value, "");
|
||||
|
||||
static_assert(std::is_constructible<
|
||||
message<true, two_arg_body, headers>, std::piecewise_construct_t,
|
||||
message<true, two_arg_body, fields>, std::piecewise_construct_t,
|
||||
std::tuple<Arg1, Arg2>>::value, "");
|
||||
|
||||
static_assert(std::is_constructible<
|
||||
message<true, two_arg_body, headers>, std::piecewise_construct_t,
|
||||
std::tuple<Arg1, Arg2>, std::tuple<headers::allocator_type>>::value, "");
|
||||
message<true, two_arg_body, fields>, std::piecewise_construct_t,
|
||||
std::tuple<Arg1, Arg2>, std::tuple<fields::allocator_type>>::value, "");
|
||||
|
||||
{
|
||||
Arg1 arg1;
|
||||
message<true, one_arg_body, headers>{std::move(arg1)};
|
||||
message<true, one_arg_body, fields>{std::move(arg1)};
|
||||
BEAST_EXPECT(arg1.moved);
|
||||
}
|
||||
|
||||
{
|
||||
headers h;
|
||||
fields h;
|
||||
h.insert("User-Agent", "test");
|
||||
message<true, one_arg_body, headers> m{Arg1{}, h};
|
||||
message<true, one_arg_body, fields> m{Arg1{}, h};
|
||||
BEAST_EXPECT(h["User-Agent"] == "test");
|
||||
BEAST_EXPECT(m.headers["User-Agent"] == "test");
|
||||
BEAST_EXPECT(m.fields["User-Agent"] == "test");
|
||||
}
|
||||
{
|
||||
headers h;
|
||||
fields h;
|
||||
h.insert("User-Agent", "test");
|
||||
message<true, one_arg_body, headers> m{Arg1{}, std::move(h)};
|
||||
message<true, one_arg_body, fields> m{Arg1{}, std::move(h)};
|
||||
BEAST_EXPECT(! h.exists("User-Agent"));
|
||||
BEAST_EXPECT(m.headers["User-Agent"] == "test");
|
||||
BEAST_EXPECT(m.fields["User-Agent"] == "test");
|
||||
}
|
||||
|
||||
// swap
|
||||
message<true, string_body, headers> m1;
|
||||
message<true, string_body, headers> m2;
|
||||
message<true, string_body, fields> m1;
|
||||
message<true, string_body, fields> m2;
|
||||
m1.url = "u";
|
||||
m1.body = "1";
|
||||
m1.headers.insert("h", "v");
|
||||
m1.fields.insert("h", "v");
|
||||
m2.method = "G";
|
||||
m2.body = "2";
|
||||
swap(m1, m2);
|
||||
@@ -142,8 +142,8 @@ public:
|
||||
BEAST_EXPECT(m2.url == "u");
|
||||
BEAST_EXPECT(m1.body == "2");
|
||||
BEAST_EXPECT(m2.body == "1");
|
||||
BEAST_EXPECT(! m1.headers.exists("h"));
|
||||
BEAST_EXPECT(m2.headers.exists("h"));
|
||||
BEAST_EXPECT(! m1.fields.exists("h"));
|
||||
BEAST_EXPECT(m2.fields.exists("h"));
|
||||
}
|
||||
|
||||
struct MoveHeaders
|
||||
@@ -168,13 +168,13 @@ public:
|
||||
void testHeaders()
|
||||
{
|
||||
{
|
||||
using req_type = request_headers;
|
||||
using req_type = request_header;
|
||||
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;
|
||||
using res_type = response_header;
|
||||
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, "");
|
||||
@@ -183,12 +183,12 @@ public:
|
||||
|
||||
{
|
||||
MoveHeaders h;
|
||||
message_headers<true, MoveHeaders> r{std::move(h)};
|
||||
header<true, MoveHeaders> r{std::move(h)};
|
||||
BEAST_EXPECT(h.moved_from);
|
||||
BEAST_EXPECT(r.headers.moved_to);
|
||||
BEAST_EXPECT(r.fields.moved_to);
|
||||
request<string_body, MoveHeaders> m{std::move(r)};
|
||||
BEAST_EXPECT(r.headers.moved_from);
|
||||
BEAST_EXPECT(m.headers.moved_to);
|
||||
BEAST_EXPECT(r.fields.moved_from);
|
||||
BEAST_EXPECT(m.fields.moved_to);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,12 +199,12 @@ public:
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 11;
|
||||
m.headers.insert("Upgrade", "test");
|
||||
m.fields.insert("Upgrade", "test");
|
||||
BEAST_EXPECT(! is_upgrade(m));
|
||||
|
||||
prepare(m, connection::upgrade);
|
||||
BEAST_EXPECT(is_upgrade(m));
|
||||
BEAST_EXPECT(m.headers["Connection"] == "upgrade");
|
||||
BEAST_EXPECT(m.fields["Connection"] == "upgrade");
|
||||
|
||||
m.version = 10;
|
||||
BEAST_EXPECT(! is_upgrade(m));
|
||||
@@ -216,7 +216,7 @@ public:
|
||||
request<empty_body> m;
|
||||
m.version = 10;
|
||||
BEAST_EXPECT(! is_upgrade(m));
|
||||
m.headers.insert("Transfer-Encoding", "chunked");
|
||||
m.fields.insert("Transfer-Encoding", "chunked");
|
||||
try
|
||||
{
|
||||
prepare(m);
|
||||
@@ -225,8 +225,8 @@ public:
|
||||
catch(std::exception const&)
|
||||
{
|
||||
}
|
||||
m.headers.erase("Transfer-Encoding");
|
||||
m.headers.insert("Content-Length", "0");
|
||||
m.fields.erase("Transfer-Encoding");
|
||||
m.fields.insert("Content-Length", "0");
|
||||
try
|
||||
{
|
||||
prepare(m);
|
||||
@@ -236,8 +236,8 @@ public:
|
||||
{
|
||||
pass();
|
||||
}
|
||||
m.headers.erase("Content-Length");
|
||||
m.headers.insert("Connection", "keep-alive");
|
||||
m.fields.erase("Content-Length");
|
||||
m.fields.insert("Connection", "keep-alive");
|
||||
try
|
||||
{
|
||||
prepare(m);
|
||||
@@ -248,19 +248,19 @@ public:
|
||||
pass();
|
||||
}
|
||||
m.version = 11;
|
||||
m.headers.erase("Connection");
|
||||
m.headers.insert("Connection", "close");
|
||||
m.fields.erase("Connection");
|
||||
m.fields.insert("Connection", "close");
|
||||
BEAST_EXPECT(! is_keep_alive(m));
|
||||
}
|
||||
|
||||
void testSwap()
|
||||
{
|
||||
message<false, string_body, headers> m1;
|
||||
message<false, string_body, headers> m2;
|
||||
message<false, string_body, fields> m1;
|
||||
message<false, string_body, fields> m2;
|
||||
m1.status = 200;
|
||||
m1.version = 10;
|
||||
m1.body = "1";
|
||||
m1.headers.insert("h", "v");
|
||||
m1.fields.insert("h", "v");
|
||||
m2.status = 404;
|
||||
m2.reason = "OK";
|
||||
m2.body = "2";
|
||||
@@ -274,8 +274,8 @@ public:
|
||||
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"));
|
||||
BEAST_EXPECT(! m1.fields.exists("h"));
|
||||
BEAST_EXPECT(m2.fields.exists("h"));
|
||||
}
|
||||
|
||||
void run() override
|
||||
|
@@ -475,7 +475,7 @@ public:
|
||||
|
||||
template<class DynamicBuffer>
|
||||
void
|
||||
headers(DynamicBuffer& db)
|
||||
fields(DynamicBuffer& db)
|
||||
{
|
||||
while(rand(6))
|
||||
{
|
||||
@@ -536,7 +536,7 @@ public:
|
||||
request(DynamicBuffer& db)
|
||||
{
|
||||
write(db, method(), " ", uri(), " HTTP/1.1\r\n");
|
||||
headers(db);
|
||||
fields(db);
|
||||
body(db);
|
||||
}
|
||||
|
||||
@@ -549,7 +549,7 @@ public:
|
||||
write(db, " ", 100 + rand(401), " ");
|
||||
write(db, token());
|
||||
write(db, "\r\n");
|
||||
headers(db);
|
||||
fields(db);
|
||||
body(db);
|
||||
write(db, "\r\n");
|
||||
}
|
||||
|
@@ -736,12 +736,12 @@ nodejs_basic_parser<Derived>::cb_chunk_complete(http_parser*)
|
||||
|
||||
The parser may only be used once.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
class nodejs_parser
|
||||
: public nodejs_basic_parser<nodejs_parser<isRequest, Body, Headers>>
|
||||
: public nodejs_basic_parser<nodejs_parser<isRequest, Body, Fields>>
|
||||
{
|
||||
using message_type =
|
||||
message<isRequest, Body, Headers>;
|
||||
message<isRequest, Body, Fields>;
|
||||
|
||||
message_type m_;
|
||||
typename message_type::body_type::reader r_;
|
||||
@@ -781,7 +781,7 @@ private:
|
||||
void
|
||||
on_field(std::string const& field, std::string const& value)
|
||||
{
|
||||
m_.headers.insert(field, value);
|
||||
m_.fields.insert(field, value);
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -48,7 +48,7 @@ public:
|
||||
check("http", parse_error::invalid_chunk_size);
|
||||
check("http", parse_error::invalid_ext_name);
|
||||
check("http", parse_error::invalid_ext_val);
|
||||
check("http", parse_error::headers_too_big);
|
||||
check("http", parse_error::header_too_big);
|
||||
check("http", parse_error::body_too_big);
|
||||
check("http", parse_error::short_read);
|
||||
}
|
||||
|
@@ -122,20 +122,20 @@ public:
|
||||
[&]
|
||||
{
|
||||
testParser<nodejs_parser<
|
||||
true, streambuf_body, headers>>(
|
||||
true, streambuf_body, fields>>(
|
||||
Repeat, creq_);
|
||||
testParser<nodejs_parser<
|
||||
false, streambuf_body, headers>>(
|
||||
false, streambuf_body, fields>>(
|
||||
Repeat, cres_);
|
||||
});
|
||||
timedTest(Trials, "http::basic_parser_v1",
|
||||
[&]
|
||||
{
|
||||
testParser<parser_v1<
|
||||
true, streambuf_body, headers>>(
|
||||
true, streambuf_body, fields>>(
|
||||
Repeat, creq_);
|
||||
testParser<parser_v1<
|
||||
false, streambuf_body, headers>>(
|
||||
false, streambuf_body, fields>>(
|
||||
Repeat, cres_);
|
||||
});
|
||||
pass();
|
||||
|
@@ -9,8 +9,8 @@
|
||||
#include <beast/http/parser_v1.hpp>
|
||||
|
||||
#include <beast/core/streambuf.hpp>
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/headers_parser_v1.hpp>
|
||||
#include <beast/http/fields.hpp>
|
||||
#include <beast/http/header_parser_v1.hpp>
|
||||
#include <beast/http/parse.hpp>
|
||||
#include <beast/http/string_body.hpp>
|
||||
#include <beast/test/string_stream.hpp>
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
// consecutive empty header values
|
||||
{
|
||||
error_code ec;
|
||||
parser_v1<true, string_body, headers> p;
|
||||
parser_v1<true, string_body, fields> p;
|
||||
std::string const s =
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"X1:\r\n"
|
||||
@@ -44,12 +44,12 @@ public:
|
||||
return;
|
||||
BEAST_EXPECT(p.complete());
|
||||
auto const msg = p.release();
|
||||
BEAST_EXPECT(msg.headers.exists("X1"));
|
||||
BEAST_EXPECT(msg.headers["X1"] == "");
|
||||
BEAST_EXPECT(msg.headers.exists("X2"));
|
||||
BEAST_EXPECT(msg.headers["X2"] == "");
|
||||
BEAST_EXPECT(msg.headers.exists("X3"));
|
||||
BEAST_EXPECT(msg.headers["X3"] == "x");
|
||||
BEAST_EXPECT(msg.fields.exists("X1"));
|
||||
BEAST_EXPECT(msg.fields["X1"] == "");
|
||||
BEAST_EXPECT(msg.fields.exists("X2"));
|
||||
BEAST_EXPECT(msg.fields["X2"] == "");
|
||||
BEAST_EXPECT(msg.fields.exists("X3"));
|
||||
BEAST_EXPECT(msg.fields["X3"] == "x");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,23 +62,23 @@ public:
|
||||
"\r\n"
|
||||
"*"};
|
||||
streambuf rb;
|
||||
headers_parser_v1<true, headers> p0;
|
||||
header_parser_v1<true, fields> p0;
|
||||
parse(ss, rb, p0);
|
||||
request_headers const& reqh = p0.get();
|
||||
request_header const& reqh = p0.get();
|
||||
BEAST_EXPECT(reqh.method == "GET");
|
||||
BEAST_EXPECT(reqh.url == "/");
|
||||
BEAST_EXPECT(reqh.version == 11);
|
||||
BEAST_EXPECT(reqh.headers["User-Agent"] == "test");
|
||||
BEAST_EXPECT(reqh.headers["Content-Length"] == "1");
|
||||
parser_v1<true, string_body, headers> p =
|
||||
BEAST_EXPECT(reqh.fields["User-Agent"] == "test");
|
||||
BEAST_EXPECT(reqh.fields["Content-Length"] == "1");
|
||||
parser_v1<true, string_body, fields> p =
|
||||
with_body<string_body>(p0);
|
||||
BEAST_EXPECT(p.get().method == "GET");
|
||||
BEAST_EXPECT(p.get().url == "/");
|
||||
BEAST_EXPECT(p.get().version == 11);
|
||||
BEAST_EXPECT(p.get().headers["User-Agent"] == "test");
|
||||
BEAST_EXPECT(p.get().headers["Content-Length"] == "1");
|
||||
BEAST_EXPECT(p.get().fields["User-Agent"] == "test");
|
||||
BEAST_EXPECT(p.get().fields["Content-Length"] == "1");
|
||||
parse(ss, rb, p);
|
||||
request<string_body, headers> req = p.release();
|
||||
request<string_body, fields> req = p.release();
|
||||
BEAST_EXPECT(req.body == "*");
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
{
|
||||
error_code ec;
|
||||
parser_v1<true, string_body,
|
||||
basic_headers<std::allocator<char>>> p;
|
||||
basic_fields<std::allocator<char>>> p;
|
||||
std::string const s =
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
@@ -102,13 +102,13 @@ public:
|
||||
BEAST_EXPECT(m.method == "GET");
|
||||
BEAST_EXPECT(m.url == "/");
|
||||
BEAST_EXPECT(m.version == 11);
|
||||
BEAST_EXPECT(m.headers["User-Agent"] == "test");
|
||||
BEAST_EXPECT(m.fields["User-Agent"] == "test");
|
||||
BEAST_EXPECT(m.body == "*");
|
||||
}
|
||||
{
|
||||
error_code ec;
|
||||
parser_v1<false, string_body,
|
||||
basic_headers<std::allocator<char>>> p;
|
||||
basic_fields<std::allocator<char>>> p;
|
||||
std::string const s =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: test\r\n"
|
||||
@@ -122,13 +122,13 @@ public:
|
||||
BEAST_EXPECT(m.status == 200);
|
||||
BEAST_EXPECT(m.reason == "OK");
|
||||
BEAST_EXPECT(m.version == 11);
|
||||
BEAST_EXPECT(m.headers["Server"] == "test");
|
||||
BEAST_EXPECT(m.fields["Server"] == "test");
|
||||
BEAST_EXPECT(m.body == "*");
|
||||
}
|
||||
// skip body
|
||||
{
|
||||
error_code ec;
|
||||
parser_v1<false, string_body, headers> p;
|
||||
parser_v1<false, string_body, fields> p;
|
||||
std::string const s =
|
||||
"HTTP/1.1 200 Connection Established\r\n"
|
||||
"Proxy-Agent: Zscaler/5.1\r\n"
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "fail_parser.hpp"
|
||||
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/fields.hpp>
|
||||
#include <beast/http/streambuf_body.hpp>
|
||||
#include <beast/test/fail_stream.hpp>
|
||||
#include <beast/test/string_stream.hpp>
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
sb.prepare(len), buffer(s, len)));
|
||||
test::fail_counter fc{n};
|
||||
test::string_stream ss{ios_, s};
|
||||
parser_v1<isRequest, fail_body, headers> p{fc};
|
||||
parser_v1<isRequest, fail_body, fields> p{fc};
|
||||
error_code ec;
|
||||
parse(ss, sb, p, ec);
|
||||
if(! ec)
|
||||
@@ -172,7 +172,7 @@ public:
|
||||
{
|
||||
streambuf sb;
|
||||
test::string_stream ss(ios_, "GET / X");
|
||||
parser_v1<true, streambuf_body, headers> p;
|
||||
parser_v1<true, streambuf_body, fields> p;
|
||||
parse(ss, sb, p);
|
||||
fail();
|
||||
}
|
||||
@@ -258,7 +258,7 @@ public:
|
||||
"Content-Length: 5\r\n"
|
||||
"\r\n"
|
||||
};
|
||||
request_headers m;
|
||||
request_header m;
|
||||
try
|
||||
{
|
||||
streambuf sb;
|
||||
@@ -280,7 +280,7 @@ public:
|
||||
"Content-Length: 0\r\n"
|
||||
"\r\n"
|
||||
);
|
||||
request_headers m;
|
||||
request_header m;
|
||||
error_code ec;
|
||||
streambuf sb;
|
||||
async_read(fs, sb, m, do_yield[ec]);
|
||||
@@ -359,7 +359,7 @@ public:
|
||||
{
|
||||
streambuf sb;
|
||||
test::string_stream ss(ios_, "");
|
||||
parser_v1<true, streambuf_body, headers> p;
|
||||
parser_v1<true, streambuf_body, fields> p;
|
||||
error_code ec;
|
||||
parse(ss, sb, p, ec);
|
||||
BEAST_EXPECT(ec == boost::asio::error::eof);
|
||||
@@ -367,7 +367,7 @@ public:
|
||||
{
|
||||
streambuf sb;
|
||||
test::string_stream ss(ios_, "");
|
||||
parser_v1<true, streambuf_body, headers> p;
|
||||
parser_v1<true, streambuf_body, fields> p;
|
||||
error_code ec;
|
||||
async_parse(ss, sb, p, do_yield[ec]);
|
||||
BEAST_EXPECT(ec == boost::asio::error::eof);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#include <beast/http/streambuf_body.hpp>
|
||||
|
||||
#include <beast/core/to_string.hpp>
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/fields.hpp>
|
||||
#include <beast/http/parser_v1.hpp>
|
||||
#include <beast/http/read.hpp>
|
||||
#include <beast/http/write.hpp>
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
"\r\n"
|
||||
"xyz";
|
||||
test::string_stream ss(ios_, s);
|
||||
parser_v1<false, streambuf_body, headers> p;
|
||||
parser_v1<false, streambuf_body, fields> p;
|
||||
streambuf sb;
|
||||
parse(ss, sb, p);
|
||||
BEAST_EXPECT(to_string(p.get().body.data()) == "xyz");
|
||||
|
@@ -8,7 +8,7 @@
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/write.hpp>
|
||||
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/fields.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/empty_body.hpp>
|
||||
#include <beast/http/string_body.hpp>
|
||||
@@ -221,9 +221,9 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
std::string
|
||||
str(message<isRequest, Body, Headers> const& m)
|
||||
str(message<isRequest, Body, Fields> const& m)
|
||||
{
|
||||
string_write_stream ss(ios_);
|
||||
write(ss, m);
|
||||
@@ -234,11 +234,11 @@ public:
|
||||
testAsyncWriteHeaders(yield_context do_yield)
|
||||
{
|
||||
{
|
||||
message_headers<true, headers> m;
|
||||
header<true, fields> m;
|
||||
m.version = 11;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
error_code ec;
|
||||
string_write_stream ss{ios_};
|
||||
async_write(ss, m, do_yield[ec]);
|
||||
@@ -249,12 +249,12 @@ public:
|
||||
"\r\n");
|
||||
}
|
||||
{
|
||||
message_headers<false, headers> m;
|
||||
header<false, fields> m;
|
||||
m.version = 10;
|
||||
m.status = 200;
|
||||
m.reason = "OK";
|
||||
m.headers.insert("Server", "test");
|
||||
m.headers.insert("Content-Length", "5");
|
||||
m.fields.insert("Server", "test");
|
||||
m.fields.insert("Content-Length", "5");
|
||||
error_code ec;
|
||||
string_write_stream ss{ios_};
|
||||
async_write(ss, m, do_yield[ec]);
|
||||
@@ -271,12 +271,12 @@ public:
|
||||
testAsyncWrite(yield_context do_yield)
|
||||
{
|
||||
{
|
||||
message<false, string_body, headers> m;
|
||||
message<false, string_body, fields> m;
|
||||
m.version = 10;
|
||||
m.status = 200;
|
||||
m.reason = "OK";
|
||||
m.headers.insert("Server", "test");
|
||||
m.headers.insert("Content-Length", "5");
|
||||
m.fields.insert("Server", "test");
|
||||
m.fields.insert("Content-Length", "5");
|
||||
m.body = "*****";
|
||||
error_code ec;
|
||||
string_write_stream ss{ios_};
|
||||
@@ -290,12 +290,12 @@ public:
|
||||
"*****");
|
||||
}
|
||||
{
|
||||
message<false, string_body, headers> m;
|
||||
message<false, string_body, fields> m;
|
||||
m.version = 11;
|
||||
m.status = 200;
|
||||
m.reason = "OK";
|
||||
m.headers.insert("Server", "test");
|
||||
m.headers.insert("Transfer-Encoding", "chunked");
|
||||
m.fields.insert("Server", "test");
|
||||
m.fields.insert("Transfer-Encoding", "chunked");
|
||||
m.body = "*****";
|
||||
error_code ec;
|
||||
string_write_stream ss(ios_);
|
||||
@@ -323,14 +323,14 @@ public:
|
||||
test::fail_counter fc(n);
|
||||
test::fail_stream<
|
||||
string_write_stream> fs(fc, ios_);
|
||||
message<true, fail_body, headers> m(
|
||||
message<true, fail_body, fields> m(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(fc, ios_));
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 10;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.headers.insert("Content-Length", "5");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.fields.insert("Content-Length", "5");
|
||||
m.body = "*****";
|
||||
try
|
||||
{
|
||||
@@ -356,14 +356,14 @@ public:
|
||||
test::fail_counter fc(n);
|
||||
test::fail_stream<
|
||||
string_write_stream> fs(fc, ios_);
|
||||
message<true, fail_body, headers> m(
|
||||
message<true, fail_body, fields> m(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(fc, ios_));
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 10;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.headers.insert("Transfer-Encoding", "chunked");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.fields.insert("Transfer-Encoding", "chunked");
|
||||
m.body = "*****";
|
||||
error_code ec;
|
||||
write(fs, m, ec);
|
||||
@@ -391,14 +391,14 @@ public:
|
||||
test::fail_counter fc(n);
|
||||
test::fail_stream<
|
||||
string_write_stream> fs(fc, ios_);
|
||||
message<true, fail_body, headers> m(
|
||||
message<true, fail_body, fields> m(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(fc, ios_));
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 10;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.headers.insert("Transfer-Encoding", "chunked");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.fields.insert("Transfer-Encoding", "chunked");
|
||||
m.body = "*****";
|
||||
error_code ec;
|
||||
async_write(fs, m, do_yield[ec]);
|
||||
@@ -426,14 +426,14 @@ public:
|
||||
test::fail_counter fc(n);
|
||||
test::fail_stream<
|
||||
string_write_stream> fs(fc, ios_);
|
||||
message<true, fail_body, headers> m(
|
||||
message<true, fail_body, fields> m(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(fc, ios_));
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 10;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.headers.insert("Content-Length", "5");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.fields.insert("Content-Length", "5");
|
||||
m.body = "*****";
|
||||
error_code ec;
|
||||
write(fs, m, ec);
|
||||
@@ -456,14 +456,14 @@ public:
|
||||
test::fail_counter fc(n);
|
||||
test::fail_stream<
|
||||
string_write_stream> fs(fc, ios_);
|
||||
message<true, fail_body, headers> m(
|
||||
message<true, fail_body, fields> m(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(fc, ios_));
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 10;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.headers.insert("Content-Length", "5");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.fields.insert("Content-Length", "5");
|
||||
m.body = "*****";
|
||||
error_code ec;
|
||||
async_write(fs, m, do_yield[ec]);
|
||||
@@ -487,11 +487,11 @@ public:
|
||||
{
|
||||
// auto content-length HTTP/1.0
|
||||
{
|
||||
message<true, string_body, headers> m;
|
||||
message<true, string_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 10;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
BEAST_EXPECT(str(m) ==
|
||||
@@ -504,11 +504,11 @@ public:
|
||||
}
|
||||
// keep-alive HTTP/1.0
|
||||
{
|
||||
message<true, string_body, headers> m;
|
||||
message<true, string_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 10;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m, connection::keep_alive);
|
||||
BEAST_EXPECT(str(m) ==
|
||||
@@ -522,11 +522,11 @@ public:
|
||||
}
|
||||
// upgrade HTTP/1.0
|
||||
{
|
||||
message<true, string_body, headers> m;
|
||||
message<true, string_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 10;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
try
|
||||
{
|
||||
@@ -540,11 +540,11 @@ public:
|
||||
}
|
||||
// no content-length HTTP/1.0
|
||||
{
|
||||
message<true, unsized_body, headers> m;
|
||||
message<true, unsized_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 10;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
string_write_stream ss(ios_);
|
||||
@@ -560,11 +560,11 @@ public:
|
||||
}
|
||||
// auto content-length HTTP/1.1
|
||||
{
|
||||
message<true, string_body, headers> m;
|
||||
message<true, string_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 11;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
BEAST_EXPECT(str(m) ==
|
||||
@@ -577,11 +577,11 @@ public:
|
||||
}
|
||||
// close HTTP/1.1
|
||||
{
|
||||
message<true, string_body, headers> m;
|
||||
message<true, string_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 11;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m, connection::close);
|
||||
string_write_stream ss(ios_);
|
||||
@@ -599,11 +599,11 @@ public:
|
||||
}
|
||||
// upgrade HTTP/1.1
|
||||
{
|
||||
message<true, empty_body, headers> m;
|
||||
message<true, empty_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 11;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
prepare(m, connection::upgrade);
|
||||
BEAST_EXPECT(str(m) ==
|
||||
"GET / HTTP/1.1\r\n"
|
||||
@@ -614,11 +614,11 @@ public:
|
||||
}
|
||||
// no content-length HTTP/1.1
|
||||
{
|
||||
message<true, unsized_body, headers> m;
|
||||
message<true, unsized_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 11;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
string_write_stream ss(ios_);
|
||||
@@ -639,11 +639,11 @@ public:
|
||||
void test_std_ostream()
|
||||
{
|
||||
// Conversion to std::string via operator<<
|
||||
message<true, string_body, headers> m;
|
||||
message<true, string_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 11;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
BEAST_EXPECT(boost::lexical_cast<std::string>(m) ==
|
||||
"GET / HTTP/1.1\r\nUser-Agent: test\r\n\r\n*");
|
||||
@@ -656,7 +656,7 @@ public:
|
||||
std::stringstream::failbit);
|
||||
try
|
||||
{
|
||||
// message_headers
|
||||
// header
|
||||
ss << m.base();
|
||||
fail("", __FILE__, __LINE__);
|
||||
}
|
||||
@@ -679,11 +679,11 @@ public:
|
||||
|
||||
void testOstream()
|
||||
{
|
||||
message<true, string_body, headers> m;
|
||||
message<true, string_body, fields> m;
|
||||
m.method = "GET";
|
||||
m.url = "/";
|
||||
m.version = 11;
|
||||
m.headers.insert("User-Agent", "test");
|
||||
m.fields.insert("User-Agent", "test");
|
||||
m.body = "*";
|
||||
prepare(m);
|
||||
std::stringstream ss;
|
||||
|
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
void testFrameHeader()
|
||||
{
|
||||
// good frame headers
|
||||
// good frame fields
|
||||
{
|
||||
role_type role = role_type::client;
|
||||
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
check(fh);
|
||||
}
|
||||
|
||||
// bad frame headers
|
||||
// bad frame fields
|
||||
{
|
||||
role_type role = role_type::client;
|
||||
|
||||
@@ -211,7 +211,7 @@ public:
|
||||
|
||||
void testBadFrameHeaders()
|
||||
{
|
||||
// bad frame headers
|
||||
// bad frame fields
|
||||
//
|
||||
// can't be created by the library
|
||||
// so we produce them manually.
|
||||
|
@@ -133,15 +133,15 @@ public:
|
||||
|
||||
struct identity
|
||||
{
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
operator()(http::message<true, Body, Headers>&)
|
||||
operator()(http::message<true, Body, Fields>&)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
operator()(http::message<false, Body, Headers>&)
|
||||
operator()(http::message<false, Body, Fields>&)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -188,11 +188,11 @@ public:
|
||||
req.method = "GET";
|
||||
req.url = "/";
|
||||
req.version = 11;
|
||||
req.headers.insert("Host", "localhost");
|
||||
req.headers.insert("Upgrade", "websocket");
|
||||
req.headers.insert("Connection", "upgrade");
|
||||
req.headers.insert("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
|
||||
req.headers.insert("Sec-WebSocket-Version", "13");
|
||||
req.fields.insert("Host", "localhost");
|
||||
req.fields.insert("Upgrade", "websocket");
|
||||
req.fields.insert("Connection", "upgrade");
|
||||
req.fields.insert("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
|
||||
req.fields.insert("Sec-WebSocket-Version", "13");
|
||||
stream<test::fail_stream<
|
||||
test::string_stream>> ws(n, ios_, "");
|
||||
try
|
||||
|
@@ -135,18 +135,18 @@ private:
|
||||
|
||||
struct identity
|
||||
{
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
operator()(http::message<true, Body, Headers>& req)
|
||||
operator()(http::message<true, Body, Fields>& req)
|
||||
{
|
||||
req.headers.replace("User-Agent", "async_echo_client");
|
||||
req.fields.replace("User-Agent", "async_echo_client");
|
||||
}
|
||||
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
operator()(http::message<false, Body, Headers>& resp)
|
||||
operator()(http::message<false, Body, Fields>& resp)
|
||||
{
|
||||
resp.headers.replace("Server", "async_echo_server");
|
||||
resp.fields.replace("Server", "async_echo_server");
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -138,18 +138,18 @@ private:
|
||||
|
||||
struct identity
|
||||
{
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
operator()(http::message<true, Body, Headers>& req)
|
||||
operator()(http::message<true, Body, Fields>& req)
|
||||
{
|
||||
req.headers.replace("User-Agent", "sync_echo_client");
|
||||
req.fields.replace("User-Agent", "sync_echo_client");
|
||||
}
|
||||
|
||||
template<class Body, class Headers>
|
||||
template<class Body, class Fields>
|
||||
void
|
||||
operator()(http::message<false, Body, Headers>& resp)
|
||||
operator()(http::message<false, Body, Fields>& resp)
|
||||
{
|
||||
resp.headers.replace("Server", "sync_echo_server");
|
||||
resp.fields.replace("Server", "sync_echo_server");
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user