mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 05:17:26 +02:00
Distinguish HTTP/1 messages from general HTTP messages:
The version field is moved into message_v1, all public interfaces are reworked to identify HTTP/1 wire format operations (suffix "_v1") versus general HTTP.
This commit is contained in:
@ -122,12 +122,14 @@ INPUT = \
|
|||||||
../include/beast/write_streambuf.hpp \
|
../include/beast/write_streambuf.hpp \
|
||||||
../include/beast/http/basic_headers.hpp \
|
../include/beast/http/basic_headers.hpp \
|
||||||
../include/beast/http/basic_parser.hpp \
|
../include/beast/http/basic_parser.hpp \
|
||||||
|
../include/beast/http/body_writer.hpp \
|
||||||
../include/beast/http/chunk_encode.hpp \
|
../include/beast/http/chunk_encode.hpp \
|
||||||
../include/beast/http/empty_body.hpp \
|
../include/beast/http/empty_body.hpp \
|
||||||
../include/beast/http/error.hpp \
|
../include/beast/http/error.hpp \
|
||||||
../include/beast/http/fields.hpp \
|
../include/beast/http/fields.hpp \
|
||||||
../include/beast/http/headers.hpp \
|
../include/beast/http/headers.hpp \
|
||||||
../include/beast/http/message.hpp \
|
../include/beast/http/message.hpp \
|
||||||
|
../include/beast/http/message_v1.hpp \
|
||||||
../include/beast/http/method.hpp \
|
../include/beast/http/method.hpp \
|
||||||
../include/beast/http/parse_error.hpp \
|
../include/beast/http/parse_error.hpp \
|
||||||
../include/beast/http/parser.hpp \
|
../include/beast/http/parser.hpp \
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||||
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/body_writer.hpp>
|
||||||
#include <beast/http/resume_context.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@ -44,7 +43,8 @@ struct file_body
|
|||||||
std::size_t buf_len_;
|
std::size_t buf_len_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool constexpr is_single_pass = false;
|
writer(writer const&) = delete;
|
||||||
|
writer& operator=(writer const&) = delete;
|
||||||
|
|
||||||
template<bool isRequest, class Headers>
|
template<bool isRequest, class Headers>
|
||||||
writer(message<isRequest, file_body, Headers> const& m) noexcept
|
writer(message<isRequest, file_body, Headers> const& m) noexcept
|
||||||
|
@ -41,8 +41,8 @@ class http_async_server
|
|||||||
using address_type = boost::asio::ip::address;
|
using address_type = boost::asio::ip::address;
|
||||||
using socket_type = boost::asio::ip::tcp::socket;
|
using socket_type = boost::asio::ip::tcp::socket;
|
||||||
|
|
||||||
using req_type = request<string_body>;
|
using req_type = request_v1<string_body>;
|
||||||
using resp_type = response<file_body>;
|
using resp_type = response_v1<file_body>;
|
||||||
|
|
||||||
boost::asio::io_service ios_;
|
boost::asio::io_service ios_;
|
||||||
socket_type sock_;
|
socket_type sock_;
|
||||||
@ -127,7 +127,7 @@ private:
|
|||||||
path = root_ + path;
|
path = root_ + path;
|
||||||
if(! boost::filesystem::exists(path))
|
if(! boost::filesystem::exists(path))
|
||||||
{
|
{
|
||||||
response<string_body> resp(
|
response_v1<string_body> resp(
|
||||||
{404, "Not Found", req_.version});
|
{404, "Not Found", req_.version});
|
||||||
resp.headers.replace("Server", "http_async_server");
|
resp.headers.replace("Server", "http_async_server");
|
||||||
resp.body = "The file '" + path + "' was not found";
|
resp.body = "The file '" + path + "' was not found";
|
||||||
@ -137,7 +137,7 @@ private:
|
|||||||
asio::placeholders::error));
|
asio::placeholders::error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
response<file_body> resp(
|
resp_type resp(
|
||||||
{200, "OK", req_.version});
|
{200, "OK", req_.version});
|
||||||
resp.headers.replace("Server", "http_async_server");
|
resp.headers.replace("Server", "http_async_server");
|
||||||
resp.headers.replace("Content-Type", "text/html");
|
resp.headers.replace("Content-Type", "text/html");
|
||||||
|
@ -46,13 +46,13 @@ int main(int, char const*[])
|
|||||||
stream<ip::tcp::socket> hs(ios);
|
stream<ip::tcp::socket> hs(ios);
|
||||||
connect(hs.lowest_layer(), it);
|
connect(hs.lowest_layer(), it);
|
||||||
auto ep = hs.lowest_layer().remote_endpoint();
|
auto ep = hs.lowest_layer().remote_endpoint();
|
||||||
request<empty_body> req({"GET", "/", 11});
|
request_v1<empty_body> req({"GET", "/", 11});
|
||||||
req.headers.insert("Host", host +
|
req.headers.insert("Host", host +
|
||||||
std::string(":") + std::to_string(ep.port()));
|
std::string(":") + std::to_string(ep.port()));
|
||||||
req.headers.insert("User-Agent", "beast/http");
|
req.headers.insert("User-Agent", "beast/http");
|
||||||
prepare(req);
|
prepare(req);
|
||||||
hs.write(req);
|
hs.write(req);
|
||||||
response<string_body> resp;
|
response_v1<string_body> resp;
|
||||||
hs.read(resp);
|
hs.read(resp);
|
||||||
std::cout << resp;
|
std::cout << resp;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ int main()
|
|||||||
using namespace beast::http;
|
using namespace beast::http;
|
||||||
|
|
||||||
// Send HTTP request using beast
|
// Send HTTP request using beast
|
||||||
request<empty_body> req({"GET", "/", 11});
|
request_v1<empty_body> req({"GET", "/", 11});
|
||||||
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
|
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
|
||||||
req.headers.replace("User-Agent", "Beast");
|
req.headers.replace("User-Agent", "Beast");
|
||||||
prepare(req);
|
prepare(req);
|
||||||
@ -31,7 +31,7 @@ int main()
|
|||||||
|
|
||||||
// Receive and print HTTP response using beast
|
// Receive and print HTTP response using beast
|
||||||
beast::streambuf sb;
|
beast::streambuf sb;
|
||||||
response<streambuf_body> resp;
|
response_v1<streambuf_body> resp;
|
||||||
read(sock, sb, resp);
|
read(sock, sb, resp);
|
||||||
std::cout << resp;
|
std::cout << resp;
|
||||||
}
|
}
|
||||||
|
@ -268,7 +268,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(message<isRequest, Body, Headers>& msg)
|
read(message_v1<isRequest, Body, Headers>& msg)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
read(msg, ec);
|
read(msg, ec);
|
||||||
@ -295,7 +295,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(message<isRequest, Body, Headers>& msg,
|
read(message_v1<isRequest, Body, Headers>& msg,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start reading a HTTP message from the stream asynchronously.
|
/** Start reading a HTTP message from the stream asynchronously.
|
||||||
@ -339,7 +339,7 @@ public:
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_read(message<isRequest, Body, Headers>& msg,
|
async_read(message_v1<isRequest, Body, Headers>& msg,
|
||||||
ReadHandler&& handler);
|
ReadHandler&& handler);
|
||||||
|
|
||||||
/** Write a HTTP message to the stream.
|
/** Write a HTTP message to the stream.
|
||||||
@ -365,7 +365,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(message<isRequest, Body, Headers> const& msg)
|
write(message_v1<isRequest, Body, Headers> const& msg)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
write(msg, ec);
|
write(msg, ec);
|
||||||
@ -396,7 +396,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(message<isRequest, Body, Headers> const& msg,
|
write(message_v1<isRequest, Body, Headers> const& msg,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start pipelining a HTTP message to the stream asynchronously.
|
/** Start pipelining a HTTP message to the stream asynchronously.
|
||||||
@ -434,7 +434,7 @@ public:
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_write(message<isRequest, Body, Headers> const& msg,
|
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
/** Start pipelining a HTTP message to the stream asynchronously.
|
/** Start pipelining a HTTP message to the stream asynchronously.
|
||||||
@ -473,7 +473,7 @@ public:
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_write(message<isRequest, Body, Headers>&& msg,
|
async_write(message_v1<isRequest, Body, Headers>&& msg,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -20,10 +20,11 @@
|
|||||||
#ifndef BEAST_HTTP_STREAM_IPP_INCLUDED
|
#ifndef BEAST_HTTP_STREAM_IPP_INCLUDED
|
||||||
#define BEAST_HTTP_STREAM_IPP_INCLUDED
|
#define BEAST_HTTP_STREAM_IPP_INCLUDED
|
||||||
|
|
||||||
#include <beast/bind_handler.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/handler_alloc.hpp>
|
|
||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
|
#include <beast/bind_handler.hpp>
|
||||||
|
#include <beast/handler_alloc.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@ -40,14 +41,14 @@ class stream<NextLayer, Allocator>::read_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& s;
|
stream<NextLayer>& s;
|
||||||
message<isRequest, Body, Headers>& m;
|
message_v1<isRequest, Body, Headers>& m;
|
||||||
Handler h;
|
Handler h;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
||||||
message<isRequest, Body, Headers>& m_)
|
message_v1<isRequest, Body, Headers>& m_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, m(m_)
|
, m(m_)
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
, h(std::forward<DeducedHandler>(h_))
|
||||||
@ -142,14 +143,14 @@ class stream<NextLayer, Allocator>::write_op : public op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& s;
|
stream<NextLayer>& s;
|
||||||
message<isRequest, Body, Headers> m;
|
message_v1<isRequest, Body, Headers> m;
|
||||||
Handler h;
|
Handler h;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
||||||
message<isRequest, Body, Headers> const& m_,
|
message_v1<isRequest, Body, Headers> const& m_,
|
||||||
bool cont_)
|
bool cont_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, m(m_)
|
, m(m_)
|
||||||
@ -160,7 +161,7 @@ class stream<NextLayer, Allocator>::write_op : public op
|
|||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
data(DeducedHandler&& h_, stream<NextLayer>& s_,
|
||||||
message<isRequest, Body, Headers>&& m_,
|
message_v1<isRequest, Body, Headers>&& m_,
|
||||||
bool cont_)
|
bool cont_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, m(std::move(m_))
|
, m(std::move(m_))
|
||||||
@ -305,7 +306,7 @@ template<class NextLayer, class Allocator>
|
|||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
read(message<isRequest, Body, Headers>& msg,
|
read(message_v1<isRequest, Body, Headers>& msg,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
beast::http::read(next_layer_, rd_buf_, msg, ec);
|
beast::http::read(next_layer_, rd_buf_, msg, ec);
|
||||||
@ -316,7 +317,7 @@ template<bool isRequest, class Body, class Headers,
|
|||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
auto
|
auto
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
async_read(message<isRequest, Body, Headers>& msg,
|
async_read(message_v1<isRequest, Body, Headers>& msg,
|
||||||
ReadHandler&& handler) ->
|
ReadHandler&& handler) ->
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
@ -334,7 +335,7 @@ template<class NextLayer, class Allocator>
|
|||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
write(message<isRequest, Body, Headers> const& msg,
|
write(message_v1<isRequest, Body, Headers> const& msg,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
beast::http::write(next_layer_, msg, ec);
|
beast::http::write(next_layer_, msg, ec);
|
||||||
@ -345,7 +346,7 @@ template<bool isRequest, class Body, class Headers,
|
|||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
auto
|
auto
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
async_write(message<isRequest, Body, Headers> const& msg,
|
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler) ->
|
WriteHandler&& handler) ->
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
@ -376,7 +377,7 @@ template<bool isRequest, class Body, class Headers,
|
|||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
auto
|
auto
|
||||||
stream<NextLayer, Allocator>::
|
stream<NextLayer, Allocator>::
|
||||||
async_write(message<isRequest, Body, Headers>&& msg,
|
async_write(message_v1<isRequest, Body, Headers>&& msg,
|
||||||
WriteHandler&& handler) ->
|
WriteHandler&& handler) ->
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
|
@ -43,8 +43,8 @@ class http_sync_server
|
|||||||
using address_type = boost::asio::ip::address;
|
using address_type = boost::asio::ip::address;
|
||||||
using socket_type = boost::asio::ip::tcp::socket;
|
using socket_type = boost::asio::ip::tcp::socket;
|
||||||
|
|
||||||
using req_type = request<string_body>;
|
using req_type = request_v1<string_body>;
|
||||||
using resp_type = response<file_body>;
|
using resp_type = response_v1<file_body>;
|
||||||
|
|
||||||
boost::asio::io_service ios_;
|
boost::asio::io_service ios_;
|
||||||
socket_type sock_;
|
socket_type sock_;
|
||||||
@ -155,7 +155,7 @@ public:
|
|||||||
path = root_ + path;
|
path = root_ + path;
|
||||||
if(! boost::filesystem::exists(path))
|
if(! boost::filesystem::exists(path))
|
||||||
{
|
{
|
||||||
response<string_body> resp(
|
response_v1<string_body> resp(
|
||||||
{404, "Not Found", req.version});
|
{404, "Not Found", req.version});
|
||||||
resp.headers.replace("Server", "http_sync_server");
|
resp.headers.replace("Server", "http_sync_server");
|
||||||
resp.body = "The file '" + path + "' was not found";
|
resp.body = "The file '" + path + "' was not found";
|
||||||
@ -164,7 +164,7 @@ public:
|
|||||||
if(ec)
|
if(ec)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
response<file_body> resp(
|
resp_type resp(
|
||||||
{200, "OK", req.version});
|
{200, "OK", req.version});
|
||||||
resp.headers.replace("Server", "http_sync_server");
|
resp.headers.replace("Server", "http_sync_server");
|
||||||
resp.headers.replace("Content-Type", "text/html");
|
resp.headers.replace("Content-Type", "text/html");
|
||||||
|
@ -9,13 +9,15 @@
|
|||||||
#define BEAST_HTTP_HPP_INCLUDED
|
#define BEAST_HTTP_HPP_INCLUDED
|
||||||
|
|
||||||
#include <beast/http/basic_headers.hpp>
|
#include <beast/http/basic_headers.hpp>
|
||||||
#include <beast/http/basic_parser.hpp>
|
#include <beast/http/basic_parser_v1.hpp>
|
||||||
|
#include <beast/http/body_writer.hpp>
|
||||||
#include <beast/http/empty_body.hpp>
|
#include <beast/http/empty_body.hpp>
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/error.hpp>
|
||||||
#include <beast/http/headers.hpp>
|
#include <beast/http/headers.hpp>
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message.hpp>
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/http/parse_error.hpp>
|
#include <beast/http/parse_error.hpp>
|
||||||
#include <beast/http/parser.hpp>
|
#include <beast/http/parser_v1.hpp>
|
||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/http/reason.hpp>
|
#include <beast/http/reason.hpp>
|
||||||
#include <beast/http/resume_context.hpp>
|
#include <beast/http/resume_context.hpp>
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_BASIC_PARSER_HPP
|
#ifndef BEAST_HTTP_BASIC_PARSER_v1_HPP
|
||||||
#define BEAST_HTTP_BASIC_PARSER_HPP
|
#define BEAST_HTTP_BASIC_PARSER_v1_HPP
|
||||||
|
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message.hpp>
|
||||||
#include <beast/http/parse_error.hpp>
|
#include <beast/http/parse_error.hpp>
|
||||||
#include <beast/http/rfc7230.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
#include <beast/http/detail/basic_parser.hpp>
|
#include <beast/http/detail/basic_parser_v1.hpp>
|
||||||
#include <beast/type_check.hpp>
|
#include <beast/type_check.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -37,7 +37,7 @@ enum values
|
|||||||
};
|
};
|
||||||
} // parse_flag
|
} // parse_flag
|
||||||
|
|
||||||
/** Parser for producing HTTP requests and responses.
|
/** Base class for parsing HTTP/1 requests and responses.
|
||||||
|
|
||||||
During parsing, callbacks will be made to the derived class
|
During parsing, callbacks will be made to the derived class
|
||||||
if those members are present (detected through SFINAE). The
|
if those members are present (detected through SFINAE). The
|
||||||
@ -84,7 +84,7 @@ enum values
|
|||||||
@li `void on_complete(error_code& ec)`
|
@li `void on_complete(error_code& ec)`
|
||||||
|
|
||||||
Called when the entire message has been parsed successfully.
|
Called when the entire message has been parsed successfully.
|
||||||
At this point, basic_parser::complete() returns `true`, and
|
At this point, basic_parser_v1::complete() returns `true`, and
|
||||||
the parser is ready to parse another message if keep_alive()
|
the parser is ready to parse another message if keep_alive()
|
||||||
would return `true`.
|
would return `true`.
|
||||||
|
|
||||||
@ -109,10 +109,10 @@ enum values
|
|||||||
and the error is returned to the caller.
|
and the error is returned to the caller.
|
||||||
*/
|
*/
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
class basic_parser
|
class basic_parser_v1
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using self = basic_parser;
|
using self = basic_parser_v1;
|
||||||
typedef void(self::*pmf_t)(error_code&, boost::string_ref const&);
|
typedef void(self::*pmf_t)(error_code&, boost::string_ref const&);
|
||||||
|
|
||||||
static std::uint64_t constexpr no_content_length =
|
static std::uint64_t constexpr no_content_length =
|
||||||
@ -237,13 +237,13 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/// Copy constructor.
|
/// Copy constructor.
|
||||||
basic_parser(basic_parser const&) = default;
|
basic_parser_v1(basic_parser_v1 const&) = default;
|
||||||
|
|
||||||
/// Copy assignment.
|
/// Copy assignment.
|
||||||
basic_parser& operator=(basic_parser const&) = default;
|
basic_parser_v1& operator=(basic_parser_v1 const&) = default;
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
basic_parser()
|
basic_parser_v1()
|
||||||
{
|
{
|
||||||
init(std::integral_constant<bool, isRequest>{});
|
init(std::integral_constant<bool, isRequest>{});
|
||||||
}
|
}
|
||||||
@ -759,6 +759,6 @@ private:
|
|||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
#include <beast/http/impl/basic_parser.ipp>
|
#include <beast/http/impl/basic_parser_v1.ipp>
|
||||||
|
|
||||||
#endif
|
#endif
|
19
include/beast/http/body_writer.hpp
Normal file
19
include/beast/http/body_writer.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// 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_WRITER_HPP
|
||||||
|
#define BEAST_HTTP_BODY_WRITER_HPP
|
||||||
|
|
||||||
|
// Convenience header to include everything necessary for
|
||||||
|
// declaring an object meeting the BodyWriter requirements.
|
||||||
|
|
||||||
|
#include <beast/http/error.hpp>
|
||||||
|
#include <beast/http/message.hpp>
|
||||||
|
#include <beast/http/resume_context.hpp>
|
||||||
|
#include <boost/logic/tribool.hpp>
|
||||||
|
|
||||||
|
#endif
|
@ -5,8 +5,8 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_DETAIL_BASIC_PARSER_HPP
|
#ifndef BEAST_HTTP_DETAIL_BASIC_PARSER_V1_HPP
|
||||||
#define BEAST_HTTP_DETAIL_BASIC_PARSER_HPP
|
#define BEAST_HTTP_DETAIL_BASIC_PARSER_V1_HPP
|
||||||
|
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
#include <boost/utility/string_ref.hpp>
|
#include <boost/utility/string_ref.hpp>
|
43
include/beast/http/detail/has_content_length.hpp
Normal file
43
include/beast/http/detail/has_content_length.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// 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_HAS_CONTENT_LENGTH_HPP
|
||||||
|
#define BEAST_HTTP_DETAIL_HAS_CONTENT_LENGTH_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class has_content_length_value
|
||||||
|
{
|
||||||
|
template<class U, class R = typename std::is_convertible<
|
||||||
|
decltype(std::declval<U>().content_length()),
|
||||||
|
std::uint64_t>>
|
||||||
|
static R check(int);
|
||||||
|
template <class>
|
||||||
|
static std::false_type check(...);
|
||||||
|
using type = decltype(check<T>(0));
|
||||||
|
public:
|
||||||
|
// `true` if `T` meets the requirements.
|
||||||
|
static bool const value = type::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determines if the writer can provide the content length
|
||||||
|
template<class T>
|
||||||
|
using has_content_length =
|
||||||
|
std::integral_constant<bool,
|
||||||
|
has_content_length_value<T>::value>;
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
@ -1,83 +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_DETAIL_WRITE_PREPARATION_HPP
|
|
||||||
#define BEAST_HTTP_DETAIL_WRITE_PREPARATION_HPP
|
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
|
||||||
#include <beast/http/rfc2616.hpp>
|
|
||||||
#include <beast/streambuf.hpp>
|
|
||||||
#include <beast/write_streambuf.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class has_content_length_value
|
|
||||||
{
|
|
||||||
template<class U, class R = typename std::is_convertible<
|
|
||||||
decltype(std::declval<U>().content_length()),
|
|
||||||
std::size_t>>
|
|
||||||
static R check(int);
|
|
||||||
template <class>
|
|
||||||
static std::false_type check(...);
|
|
||||||
using type = decltype(check<T>(0));
|
|
||||||
public:
|
|
||||||
// `true` if `T` meets the requirements.
|
|
||||||
static bool const value = type::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Determines if the writer can provide the content length
|
|
||||||
template<class T>
|
|
||||||
using has_content_length =
|
|
||||||
std::integral_constant<bool,
|
|
||||||
has_content_length_value<T>::value>;
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
struct write_preparation
|
|
||||||
{
|
|
||||||
using headers_type =
|
|
||||||
basic_headers<std::allocator<char>>;
|
|
||||||
|
|
||||||
message<isRequest, Body, Headers> const& msg;
|
|
||||||
typename Body::writer w;
|
|
||||||
streambuf sb;
|
|
||||||
bool chunked;
|
|
||||||
bool close;
|
|
||||||
|
|
||||||
explicit
|
|
||||||
write_preparation(
|
|
||||||
message<isRequest, Body, Headers> const& msg_)
|
|
||||||
: msg(msg_)
|
|
||||||
, w(msg)
|
|
||||||
, chunked(rfc2616::token_in_list(
|
|
||||||
msg.headers["Transfer-Encoding"], "chunked"))
|
|
||||||
, close(rfc2616::token_in_list(
|
|
||||||
msg.headers["Connection"], "close") ||
|
|
||||||
(msg.version < 11 && ! msg.headers.exists(
|
|
||||||
"Content-Length")))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
init(error_code& ec)
|
|
||||||
{
|
|
||||||
w.init(ec);
|
|
||||||
if(ec)
|
|
||||||
return;
|
|
||||||
msg.write_firstline(sb);
|
|
||||||
write_fields(sb, msg.headers);
|
|
||||||
beast::write(sb, "\r\n");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
} // http
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
@ -8,8 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_EMPTY_BODY_HPP
|
#ifndef BEAST_HTTP_EMPTY_BODY_HPP
|
||||||
#define BEAST_HTTP_EMPTY_BODY_HPP
|
#define BEAST_HTTP_EMPTY_BODY_HPP
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/body_writer.hpp>
|
||||||
#include <beast/http/message.hpp>
|
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -35,9 +34,9 @@ private:
|
|||||||
|
|
||||||
struct reader
|
struct reader
|
||||||
{
|
{
|
||||||
template<bool isRequest, class Allocator>
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
reader(message<isRequest, empty_body, Allocator>&)
|
reader(message<isRequest, empty_body, Headers>&)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,9 +48,12 @@ private:
|
|||||||
|
|
||||||
struct writer
|
struct writer
|
||||||
{
|
{
|
||||||
template<bool isRequest, class Allocator>
|
writer(writer const&) = delete;
|
||||||
|
writer& operator=(writer const&) = delete;
|
||||||
|
|
||||||
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, empty_body, Allocator> const& m)
|
writer(message<isRequest, empty_body, Headers> const& m)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,15 +5,15 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||||
#define BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
#define BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
bool
|
bool
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
keep_alive() const
|
keep_alive() const
|
||||||
{
|
{
|
||||||
if(http_major_ > 0 && http_minor_ > 0)
|
if(http_major_ > 0 && http_minor_ > 0)
|
||||||
@ -34,7 +34,7 @@ keep_alive() const
|
|||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
template<class ConstBufferSequence, class>
|
template<class ConstBufferSequence, class>
|
||||||
std::size_t
|
std::size_t
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
write(ConstBufferSequence const& buffers, error_code& ec)
|
write(ConstBufferSequence const& buffers, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_ConstBufferSequence<ConstBufferSequence>::value,
|
static_assert(is_ConstBufferSequence<ConstBufferSequence>::value,
|
||||||
@ -51,7 +51,7 @@ write(ConstBufferSequence const& buffers, error_code& ec)
|
|||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
std::size_t
|
std::size_t
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
write(boost::asio::const_buffer const& buffer, error_code& ec)
|
write(boost::asio::const_buffer const& buffer, error_code& ec)
|
||||||
{
|
{
|
||||||
using beast::http::detail::is_digit;
|
using beast::http::detail::is_digit;
|
||||||
@ -1022,7 +1022,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
|
|||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
void
|
void
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
write_eof(error_code& ec)
|
write_eof(error_code& ec)
|
||||||
{
|
{
|
||||||
switch(s_)
|
switch(s_)
|
||||||
@ -1042,7 +1042,7 @@ write_eof(error_code& ec)
|
|||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
bool
|
bool
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
needs_eof(std::true_type) const
|
needs_eof(std::true_type) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -1050,7 +1050,7 @@ needs_eof(std::true_type) const
|
|||||||
|
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
bool
|
bool
|
||||||
basic_parser<isRequest, Derived>::
|
basic_parser_v1<isRequest, Derived>::
|
||||||
needs_eof(std::false_type) const
|
needs_eof(std::false_type) const
|
||||||
{
|
{
|
||||||
// See RFC 2616 section 4.4
|
// See RFC 2616 section 4.4
|
@ -5,33 +5,21 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_IMPL_MESSAGE_IPP
|
#ifndef BEAST_HTTP_IMPL_MESSAGE_V1_IPP
|
||||||
#define BEAST_HTTP_IMPL_MESSAGE_IPP
|
#define BEAST_HTTP_IMPL_MESSAGE_V1_IPP
|
||||||
|
|
||||||
#include <beast/http/resume_context.hpp>
|
|
||||||
#include <beast/http/rfc2616.hpp>
|
#include <beast/http/rfc2616.hpp>
|
||||||
#include <beast/write_streambuf.hpp>
|
#include <beast/http/detail/has_content_length.hpp>
|
||||||
#include <beast/type_check.hpp>
|
#include <beast/type_check.hpp>
|
||||||
#include <beast/http/detail/write_preparation.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <boost/logic/tribool.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <condition_variable>
|
|
||||||
#include <mutex>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
message<isRequest, Body, Headers>::
|
message_v1<isRequest, Body, Headers>::
|
||||||
message()
|
message_v1(request_params params)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
message<isRequest, Body, Headers>::
|
|
||||||
message(request_params params)
|
|
||||||
{
|
{
|
||||||
static_assert(isRequest, "message is not a request");
|
static_assert(isRequest, "message is not a request");
|
||||||
this->method = params.method;
|
this->method = params.method;
|
||||||
@ -40,8 +28,8 @@ message(request_params params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
message<isRequest, Body, Headers>::
|
message_v1<isRequest, Body, Headers>::
|
||||||
message(response_params params)
|
message_v1(response_params params)
|
||||||
{
|
{
|
||||||
static_assert(! isRequest, "message is not a response");
|
static_assert(! isRequest, "message is not a response");
|
||||||
this->status = params.status;
|
this->status = params.status;
|
||||||
@ -49,126 +37,11 @@ message(response_params params)
|
|||||||
version = params.version;
|
version = params.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
message<isRequest, Body, Headers>::
|
|
||||||
write_firstline(Streambuf& streambuf,
|
|
||||||
std::true_type) const
|
|
||||||
{
|
|
||||||
write(streambuf, this->method);
|
|
||||||
write(streambuf, " ");
|
|
||||||
write(streambuf, this->url);
|
|
||||||
switch(version)
|
|
||||||
{
|
|
||||||
case 10:
|
|
||||||
write(streambuf, " HTTP/1.0\r\n");
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
write(streambuf, " HTTP/1.1\r\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
write(streambuf, " HTTP/");
|
|
||||||
write(streambuf, version / 10);
|
|
||||||
write(streambuf, ".");
|
|
||||||
write(streambuf, version % 10);
|
|
||||||
write(streambuf, "\r\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
message<isRequest, Body, Headers>::
|
|
||||||
write_firstline(Streambuf& streambuf,
|
|
||||||
std::false_type) const
|
|
||||||
{
|
|
||||||
switch(version)
|
|
||||||
{
|
|
||||||
case 10:
|
|
||||||
write(streambuf, "HTTP/1.0 ");
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
write(streambuf, "HTTP/1.1 ");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
write(streambuf, " HTTP/");
|
|
||||||
write(streambuf, version / 10);
|
|
||||||
write(streambuf, ".");
|
|
||||||
write(streambuf, version % 10);
|
|
||||||
write(streambuf, " ");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
write(streambuf, this->status);
|
|
||||||
write(streambuf, " ");
|
|
||||||
write(streambuf, this->reason);
|
|
||||||
write(streambuf, "\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
void
|
|
||||||
set_connection(bool keep_alive,
|
|
||||||
message<isRequest, Body, Headers>& req)
|
|
||||||
{
|
|
||||||
if(req.version >= 11)
|
|
||||||
{
|
|
||||||
if(! keep_alive)
|
|
||||||
req.headers.replace("Connection", "close");
|
|
||||||
else
|
|
||||||
req.headers.erase("Connection");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(keep_alive)
|
|
||||||
req.headers.replace("Connection", "keep-alive");
|
|
||||||
else
|
|
||||||
req.headers.erase("Connection");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Body, class Headers,
|
|
||||||
class OtherBody, class OtherAllocator>
|
|
||||||
void
|
|
||||||
set_connection(bool keep_alive,
|
|
||||||
message<false, Body, Headers>& resp,
|
|
||||||
message<true, OtherBody, OtherAllocator> const& req)
|
|
||||||
{
|
|
||||||
if(req.version >= 11)
|
|
||||||
{
|
|
||||||
if(rfc2616::token_in_list(req["Connection"], "close"))
|
|
||||||
keep_alive = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(! rfc2616::token_in_list(req["Connection"], "keep-alive"))
|
|
||||||
keep_alive = false;
|
|
||||||
}
|
|
||||||
set_connection(keep_alive, resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Streambuf, class FieldSequence>
|
|
||||||
void
|
|
||||||
write_fields(Streambuf& streambuf, FieldSequence const& fields)
|
|
||||||
{
|
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
|
||||||
"Streambuf requirements not met");
|
|
||||||
//static_assert(is_FieldSequence<FieldSequence>::value,
|
|
||||||
// "FieldSequence requirements not met");
|
|
||||||
for(auto const& field : fields)
|
|
||||||
{
|
|
||||||
write(streambuf, field.name());
|
|
||||||
write(streambuf, ": ");
|
|
||||||
write(streambuf, field.value());
|
|
||||||
write(streambuf, "\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
bool
|
bool
|
||||||
is_keep_alive(message<isRequest, Body, Headers> const& msg)
|
is_keep_alive(message_v1<isRequest, Body, Headers> const& msg)
|
||||||
{
|
{
|
||||||
if(msg.version >= 11)
|
if(msg.version >= 11)
|
||||||
{
|
{
|
||||||
@ -185,7 +58,7 @@ is_keep_alive(message<isRequest, Body, Headers> const& msg)
|
|||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
bool
|
bool
|
||||||
is_upgrade(message<isRequest, Body, Headers> const& msg)
|
is_upgrade(message_v1<isRequest, Body, Headers> const& msg)
|
||||||
{
|
{
|
||||||
if(msg.version < 11)
|
if(msg.version < 11)
|
||||||
return false;
|
return false;
|
||||||
@ -207,14 +80,14 @@ template<bool isRequest, class Body, class Headers>
|
|||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
prepare_options(prepare_info& pi,
|
prepare_options(prepare_info& pi,
|
||||||
message<isRequest, Body, Headers>& msg)
|
message_v1<isRequest, Body, Headers>& msg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
prepare_option(prepare_info& pi,
|
prepare_option(prepare_info& pi,
|
||||||
message<isRequest, Body, Headers>& msg,
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
connection value)
|
connection value)
|
||||||
{
|
{
|
||||||
pi.connection_value = value;
|
pi.connection_value = value;
|
||||||
@ -225,7 +98,7 @@ template<
|
|||||||
class Opt, class... Opts>
|
class Opt, class... Opts>
|
||||||
void
|
void
|
||||||
prepare_options(prepare_info& pi,
|
prepare_options(prepare_info& pi,
|
||||||
message<isRequest, Body, Headers>& msg,
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
Opt&& opt, Opts&&... opts)
|
Opt&& opt, Opts&&... opts)
|
||||||
{
|
{
|
||||||
prepare_option(pi, msg, opt);
|
prepare_option(pi, msg, opt);
|
||||||
@ -236,7 +109,7 @@ prepare_options(prepare_info& pi,
|
|||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
prepare_content_length(prepare_info& pi,
|
prepare_content_length(prepare_info& pi,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
std::true_type)
|
std::true_type)
|
||||||
{
|
{
|
||||||
typename Body::writer w(msg);
|
typename Body::writer w(msg);
|
||||||
@ -247,7 +120,7 @@ prepare_content_length(prepare_info& pi,
|
|||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
prepare_content_length(prepare_info& pi,
|
prepare_content_length(prepare_info& pi,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
std::false_type)
|
std::false_type)
|
||||||
{
|
{
|
||||||
pi.content_length = boost::none;
|
pi.content_length = boost::none;
|
||||||
@ -258,7 +131,7 @@ prepare_content_length(prepare_info& pi,
|
|||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
prepare_connection(
|
prepare_connection(
|
||||||
message<isRequest, Body, Headers>& msg)
|
message_v1<isRequest, Body, Headers>& msg)
|
||||||
{
|
{
|
||||||
if(msg.version >= 11)
|
if(msg.version >= 11)
|
||||||
{
|
{
|
||||||
@ -286,7 +159,7 @@ template<
|
|||||||
bool isRequest, class Body, class Headers,
|
bool isRequest, class Body, class Headers,
|
||||||
class... Options>
|
class... Options>
|
||||||
void
|
void
|
||||||
prepare(message<isRequest, Body, Headers>& msg,
|
prepare(message_v1<isRequest, Body, Headers>& msg,
|
||||||
Options&&... options)
|
Options&&... options)
|
||||||
{
|
{
|
||||||
// VFALCO TODO
|
// VFALCO TODO
|
@ -8,6 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
|
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||||
#define BEAST_HTTP_IMPL_READ_IPP_HPP
|
#define BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||||
|
|
||||||
|
#include <beast/http/parser_v1.hpp>
|
||||||
#include <beast/bind_handler.hpp>
|
#include <beast/bind_handler.hpp>
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -26,10 +27,10 @@ class read_op
|
|||||||
handler_alloc<char, Handler>;
|
handler_alloc<char, Handler>;
|
||||||
|
|
||||||
using parser_type =
|
using parser_type =
|
||||||
parser<isRequest, Body, Headers>;
|
parser_v1<isRequest, Body, Headers>;
|
||||||
|
|
||||||
using message_type =
|
using message_type =
|
||||||
message<isRequest, Body, Headers>;
|
message_v1<isRequest, Body, Headers>;
|
||||||
|
|
||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
@ -214,14 +215,14 @@ template<class SyncReadStream, class Streambuf,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& m,
|
message_v1<isRequest, Body, Headers>& m,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_Streambuf<Streambuf>::value,
|
||||||
"Streambuf requirements not met");
|
"Streambuf requirements not met");
|
||||||
parser<isRequest, Body, Headers> p;
|
parser_v1<isRequest, Body, Headers> p;
|
||||||
bool started = false;
|
bool started = false;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
@ -264,7 +265,7 @@ template<class AsyncReadStream, class Streambuf,
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& m,
|
message_v1<isRequest, Body, Headers>& m,
|
||||||
ReadHandler&& handler)
|
ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
||||||
|
@ -10,12 +10,13 @@
|
|||||||
|
|
||||||
#include <beast/http/resume_context.hpp>
|
#include <beast/http/resume_context.hpp>
|
||||||
#include <beast/http/detail/chunk_encode.hpp>
|
#include <beast/http/detail/chunk_encode.hpp>
|
||||||
#include <beast/http/detail/write_preparation.hpp>
|
#include <beast/http/detail/has_content_length.hpp>
|
||||||
#include <beast/buffer_cat.hpp>
|
#include <beast/buffer_cat.hpp>
|
||||||
#include <beast/bind_handler.hpp>
|
#include <beast/bind_handler.hpp>
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
#include <beast/type_check.hpp>
|
#include <beast/type_check.hpp>
|
||||||
|
#include <beast/write_streambuf.hpp>
|
||||||
#include <boost/asio/write.hpp>
|
#include <boost/asio/write.hpp>
|
||||||
#include <boost/logic/tribool.hpp>
|
#include <boost/logic/tribool.hpp>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@ -29,6 +30,114 @@ namespace http {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
template<class Streambuf, class Body, class Headers>
|
||||||
|
void
|
||||||
|
write_firstline(Streambuf& streambuf,
|
||||||
|
message_v1<true, Body, Headers> const& msg)
|
||||||
|
{
|
||||||
|
write(streambuf, msg.method);
|
||||||
|
write(streambuf, " ");
|
||||||
|
write(streambuf, msg.url);
|
||||||
|
switch(msg.version)
|
||||||
|
{
|
||||||
|
case 10:
|
||||||
|
write(streambuf, " HTTP/1.0\r\n");
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
write(streambuf, " HTTP/1.1\r\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
write(streambuf, " HTTP/");
|
||||||
|
write(streambuf, msg.version / 10);
|
||||||
|
write(streambuf, ".");
|
||||||
|
write(streambuf, msg.version % 10);
|
||||||
|
write(streambuf, "\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Streambuf, class Body, class Headers>
|
||||||
|
void
|
||||||
|
write_firstline(Streambuf& streambuf,
|
||||||
|
message_v1<false, Body, Headers> const& msg)
|
||||||
|
{
|
||||||
|
switch(msg.version)
|
||||||
|
{
|
||||||
|
case 10:
|
||||||
|
write(streambuf, "HTTP/1.0 ");
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
write(streambuf, "HTTP/1.1 ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
write(streambuf, " HTTP/");
|
||||||
|
write(streambuf, msg.version / 10);
|
||||||
|
write(streambuf, ".");
|
||||||
|
write(streambuf, msg.version % 10);
|
||||||
|
write(streambuf, " ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write(streambuf, msg.status);
|
||||||
|
write(streambuf, " ");
|
||||||
|
write(streambuf, msg.reason);
|
||||||
|
write(streambuf, "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Streambuf, class FieldSequence>
|
||||||
|
void
|
||||||
|
write_fields(Streambuf& streambuf, FieldSequence const& fields)
|
||||||
|
{
|
||||||
|
static_assert(is_Streambuf<Streambuf>::value,
|
||||||
|
"Streambuf requirements not met");
|
||||||
|
//static_assert(is_FieldSequence<FieldSequence>::value,
|
||||||
|
// "FieldSequence requirements not met");
|
||||||
|
for(auto const& field : fields)
|
||||||
|
{
|
||||||
|
write(streambuf, field.name());
|
||||||
|
write(streambuf, ": ");
|
||||||
|
write(streambuf, field.value());
|
||||||
|
write(streambuf, "\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
struct write_preparation
|
||||||
|
{
|
||||||
|
using headers_type =
|
||||||
|
basic_headers<std::allocator<char>>;
|
||||||
|
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg;
|
||||||
|
typename Body::writer w;
|
||||||
|
streambuf sb;
|
||||||
|
bool chunked;
|
||||||
|
bool close;
|
||||||
|
|
||||||
|
explicit
|
||||||
|
write_preparation(
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg_)
|
||||||
|
: msg(msg_)
|
||||||
|
, w(msg)
|
||||||
|
, chunked(rfc2616::token_in_list(
|
||||||
|
msg.headers["Transfer-Encoding"], "chunked"))
|
||||||
|
, close(rfc2616::token_in_list(
|
||||||
|
msg.headers["Connection"], "close") ||
|
||||||
|
(msg.version < 11 && ! msg.headers.exists(
|
||||||
|
"Content-Length")))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init(error_code& ec)
|
||||||
|
{
|
||||||
|
w.init(ec);
|
||||||
|
if(ec)
|
||||||
|
return;
|
||||||
|
write_firstline(sb, msg);
|
||||||
|
write_fields(sb, msg.headers);
|
||||||
|
beast::write(sb, "\r\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<class Stream, class Handler,
|
template<class Stream, class Handler,
|
||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
class write_op
|
class write_op
|
||||||
@ -50,7 +159,7 @@ class write_op
|
|||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, Stream& s_,
|
data(DeducedHandler&& h_, Stream& s_,
|
||||||
message<isRequest, Body, Headers> const& m_)
|
message_v1<isRequest, Body, Headers> const& m_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, wp(m_)
|
, wp(m_)
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
, h(std::forward<DeducedHandler>(h_))
|
||||||
@ -356,7 +465,21 @@ template<class SyncWriteStream,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(SyncWriteStream& stream,
|
write(SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg)
|
||||||
|
{
|
||||||
|
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||||
|
"SyncWriteStream requirements not met");
|
||||||
|
error_code ec;
|
||||||
|
write(stream, msg, ec);
|
||||||
|
if(ec)
|
||||||
|
throw boost::system::system_error{ec};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class SyncWriteStream,
|
||||||
|
bool isRequest, class Body, class Headers>
|
||||||
|
void
|
||||||
|
write(SyncWriteStream& stream,
|
||||||
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
boost::system::error_code& ec)
|
boost::system::error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||||
@ -441,7 +564,7 @@ template<class AsyncWriteStream,
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
async_write(AsyncWriteStream& stream,
|
async_write(AsyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler)
|
WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(
|
static_assert(
|
||||||
@ -506,7 +629,7 @@ public:
|
|||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<<(std::ostream& os,
|
operator<<(std::ostream& os,
|
||||||
message<isRequest, Body, Headers> const& msg)
|
message_v1<isRequest, Body, Headers> const& msg)
|
||||||
{
|
{
|
||||||
detail::ostream_SyncStream oss(os);
|
detail::ostream_SyncStream oss(os);
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
@ -32,24 +32,6 @@ struct response_fields
|
|||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
|
||||||
|
|
||||||
struct request_params
|
|
||||||
{
|
|
||||||
std::string method;
|
|
||||||
std::string url;
|
|
||||||
int version;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct response_params
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
std::string reason;
|
|
||||||
int version;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** A HTTP message.
|
/** A HTTP message.
|
||||||
|
|
||||||
A message can be a request or response, depending on the `isRequest`
|
A message can be a request or response, depending on the `isRequest`
|
||||||
@ -70,62 +52,24 @@ struct message
|
|||||||
: std::conditional<isRequest,
|
: std::conditional<isRequest,
|
||||||
detail::request_fields, detail::response_fields>::type
|
detail::request_fields, detail::response_fields>::type
|
||||||
{
|
{
|
||||||
/** The trait type characterizing the body.
|
/** The type controlling the body traits.
|
||||||
|
|
||||||
The body member will be of type body_type::value_type.
|
The body member will be of type `body_type::value_type`.
|
||||||
*/
|
*/
|
||||||
using body_type = Body;
|
using body_type = Body;
|
||||||
|
|
||||||
|
/// The type representing the headers.
|
||||||
using headers_type = Headers;
|
using headers_type = Headers;
|
||||||
|
|
||||||
|
/// Indicates if the message is a request.
|
||||||
using is_request =
|
using is_request =
|
||||||
std::integral_constant<bool, isRequest>;
|
std::integral_constant<bool, isRequest>;
|
||||||
|
|
||||||
int version; // 10 or 11
|
/// The container holding the headers.
|
||||||
headers_type headers;
|
headers_type headers;
|
||||||
|
|
||||||
|
/// A container representing the body.
|
||||||
typename Body::value_type body;
|
typename Body::value_type body;
|
||||||
|
|
||||||
message();
|
|
||||||
message(message&&) = default;
|
|
||||||
message(message const&) = default;
|
|
||||||
message& operator=(message&&) = default;
|
|
||||||
message& operator=(message const&) = default;
|
|
||||||
|
|
||||||
/** Construct a HTTP request.
|
|
||||||
*/
|
|
||||||
explicit
|
|
||||||
message(request_params params);
|
|
||||||
|
|
||||||
/** Construct a HTTP response.
|
|
||||||
*/
|
|
||||||
explicit
|
|
||||||
message(response_params params);
|
|
||||||
|
|
||||||
/// Serialize the request or response line to a Streambuf.
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
write_firstline(Streambuf& streambuf) const
|
|
||||||
{
|
|
||||||
write_firstline(streambuf,
|
|
||||||
std::integral_constant<bool, isRequest>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Diagnostics only
|
|
||||||
template<bool, class, class>
|
|
||||||
friend
|
|
||||||
std::ostream&
|
|
||||||
operator<<(std::ostream& os,
|
|
||||||
message const& m);
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
write_firstline(Streambuf& streambuf,
|
|
||||||
std::true_type) const;
|
|
||||||
|
|
||||||
template<class Streambuf>
|
|
||||||
void
|
|
||||||
write_firstline(Streambuf& streambuf,
|
|
||||||
std::false_type) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
#if ! GENERATING_DOCS
|
||||||
@ -142,53 +86,7 @@ using response = message<false, Body, Headers>;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Write a FieldSequence to a Streambuf.
|
|
||||||
template<class Streambuf, class FieldSequence>
|
|
||||||
void
|
|
||||||
write_fields(Streambuf& streambuf, FieldSequence const& fields);
|
|
||||||
|
|
||||||
/// Returns `true` if a message indicates a keep alive
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
bool
|
|
||||||
is_keep_alive(message<isRequest, Body, Headers> const& msg);
|
|
||||||
|
|
||||||
/// Returns `true` if a message indicates a HTTP Upgrade request or response
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
|
||||||
bool
|
|
||||||
is_upgrade(message<isRequest, Body, Headers> const& msg);
|
|
||||||
|
|
||||||
/** Connection prepare options.
|
|
||||||
|
|
||||||
These values are used with prepare().
|
|
||||||
*/
|
|
||||||
enum class connection
|
|
||||||
{
|
|
||||||
/// Indicates the message should specify Connection: close semantics
|
|
||||||
close,
|
|
||||||
|
|
||||||
/// Indicates the message should specify Connection: keep-alive semantics if possible
|
|
||||||
keep_alive,
|
|
||||||
|
|
||||||
/// Indicates the message should specify a Connection: upgrade
|
|
||||||
upgrade
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Prepare a message.
|
|
||||||
|
|
||||||
This function will adjust the Content-Length, Transfer-Encoding,
|
|
||||||
and Connection headers of the message based on the properties of
|
|
||||||
the body and the options passed in.
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
bool isRequest, class Body, class Headers,
|
|
||||||
class... Options>
|
|
||||||
void
|
|
||||||
prepare(message<isRequest, Body, Headers>& msg,
|
|
||||||
Options&&... options);
|
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
#include <beast/http/impl/message.ipp>
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
131
include/beast/http/message_v1.hpp
Normal file
131
include/beast/http/message_v1.hpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BEAST_HTTP_MESSAGE_V1_HPP
|
||||||
|
#define BEAST_HTTP_MESSAGE_V1_HPP
|
||||||
|
|
||||||
|
#include <beast/http/message.hpp>
|
||||||
|
#include <beast/type_check.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
#if ! GENERATING_DOCS
|
||||||
|
|
||||||
|
struct request_params
|
||||||
|
{
|
||||||
|
std::string method;
|
||||||
|
std::string url;
|
||||||
|
int version;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response_params
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
std::string reason;
|
||||||
|
int version;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** A HTTP/1 message.
|
||||||
|
|
||||||
|
A message can be a request or response, depending on the `isRequest`
|
||||||
|
template argument value. Requests and responses have different types,
|
||||||
|
so functions may be overloaded on them if desired.
|
||||||
|
|
||||||
|
The `Body` template argument type determines the model used
|
||||||
|
to read or write the content body of the message.
|
||||||
|
|
||||||
|
@tparam isRequest `true` if this is a request.
|
||||||
|
|
||||||
|
@tparam Body A type meeting the requirements of Body.
|
||||||
|
|
||||||
|
@tparam Headers A type meeting the requirements of Headers.
|
||||||
|
*/
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
struct message_v1 : message<isRequest, Body, Headers>
|
||||||
|
{
|
||||||
|
/// HTTP/1 version (10 or 11)
|
||||||
|
int version;
|
||||||
|
|
||||||
|
message_v1() = default;
|
||||||
|
|
||||||
|
/// Construct a HTTP/1 request.
|
||||||
|
explicit
|
||||||
|
message_v1(request_params params);
|
||||||
|
|
||||||
|
/// Construct a HTTP/1 response.
|
||||||
|
explicit
|
||||||
|
message_v1(response_params params);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ! GENERATING_DOCS
|
||||||
|
|
||||||
|
/// A typical HTTP/1 request
|
||||||
|
template<class Body,
|
||||||
|
class Headers = basic_headers<std::allocator<char>>>
|
||||||
|
using request_v1 = message_v1<true, Body, Headers>;
|
||||||
|
|
||||||
|
/// A typical HTTP/1 response
|
||||||
|
template<class Body,
|
||||||
|
class Headers = basic_headers<std::allocator<char>>>
|
||||||
|
using response_v1 = message_v1<false, Body, Headers>;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Returns `true` if a HTTP/1 message indicates a keep alive
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
bool
|
||||||
|
is_keep_alive(message_v1<isRequest, Body, Headers> const& msg);
|
||||||
|
|
||||||
|
/// Returns `true` if a HTTP/1 message indicates an Upgrade request or response
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
bool
|
||||||
|
is_upgrade(message_v1<isRequest, Body, Headers> const& msg);
|
||||||
|
|
||||||
|
/** HTTP/1 connection prepare options.
|
||||||
|
|
||||||
|
@note These values are used with `prepare`.
|
||||||
|
*/
|
||||||
|
enum class connection
|
||||||
|
{
|
||||||
|
/// Specify Connection: close.
|
||||||
|
close,
|
||||||
|
|
||||||
|
/// Specify Connection: keep-alive where possible.
|
||||||
|
keep_alive,
|
||||||
|
|
||||||
|
/// Specify Connection: upgrade.
|
||||||
|
upgrade
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Prepare a HTTP/1 message.
|
||||||
|
|
||||||
|
This function will adjust the Content-Length, Transfer-Encoding,
|
||||||
|
and Connection headers of the message based on the properties of
|
||||||
|
the body and the options passed in.
|
||||||
|
|
||||||
|
@param msg The message to prepare. The headers may be modified.
|
||||||
|
|
||||||
|
@param options A list of prepare options.
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
bool isRequest, class Body, class Headers,
|
||||||
|
class... Options>
|
||||||
|
void
|
||||||
|
prepare(message_v1<isRequest, Body, Headers>& msg,
|
||||||
|
Options&&... options);
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#include <beast/http/impl/message_v1.ipp>
|
||||||
|
|
||||||
|
#endif
|
@ -5,12 +5,12 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_PARSER_HPP
|
#ifndef BEAST_HTTP_PARSER_V1_HPP
|
||||||
#define BEAST_HTTP_PARSER_HPP
|
#define BEAST_HTTP_PARSER_V1_HPP
|
||||||
|
|
||||||
#include <beast/http/basic_parser.hpp>
|
#include <beast/http/basic_parser_v1.hpp>
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/error.hpp>
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -35,15 +35,20 @@ struct parser_response
|
|||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
|
/** A parser for producing HTTP/1 messages.
|
||||||
|
|
||||||
|
This class uses the basic HTTP/1 wire format parser to convert
|
||||||
|
a series of octets into a `message_v1`.
|
||||||
|
*/
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
class parser
|
class parser_v1
|
||||||
: public basic_parser<isRequest,
|
: public basic_parser_v1<isRequest,
|
||||||
parser<isRequest, Body, Headers>>
|
parser_v1<isRequest, Body, Headers>>
|
||||||
, private std::conditional<isRequest,
|
, private std::conditional<isRequest,
|
||||||
detail::parser_request, detail::parser_response>::type
|
detail::parser_request, detail::parser_response>::type
|
||||||
{
|
{
|
||||||
using message_type =
|
using message_type =
|
||||||
message<isRequest, Body, Headers>;
|
message_v1<isRequest, Body, Headers>;
|
||||||
|
|
||||||
std::string field_;
|
std::string field_;
|
||||||
std::string value_;
|
std::string value_;
|
||||||
@ -51,9 +56,9 @@ class parser
|
|||||||
typename message_type::body_type::reader r_;
|
typename message_type::body_type::reader r_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
parser(parser&&) = default;
|
parser_v1(parser_v1&&) = default;
|
||||||
|
|
||||||
parser()
|
parser_v1()
|
||||||
: r_(m_)
|
: r_(m_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -65,7 +70,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class basic_parser<isRequest, parser>;
|
friend class basic_parser_v1<isRequest, parser_v1>;
|
||||||
|
|
||||||
void flush()
|
void flush()
|
||||||
{
|
{
|
@ -8,16 +8,16 @@
|
|||||||
#ifndef BEAST_HTTP_READ_HPP
|
#ifndef BEAST_HTTP_READ_HPP
|
||||||
#define BEAST_HTTP_READ_HPP
|
#define BEAST_HTTP_READ_HPP
|
||||||
|
|
||||||
#include <beast/async_completion.hpp>
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/error.hpp>
|
||||||
#include <beast/http/parser.hpp>
|
#include <beast/http/parser_v1.hpp>
|
||||||
|
#include <beast/async_completion.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/** Read a HTTP message from a stream.
|
/** Read a HTTP/1 message from a stream.
|
||||||
|
|
||||||
@param stream The stream to read the message from.
|
@param stream The stream to read the message from.
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ template<class SyncReadStream, class Streambuf,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& msg)
|
message_v1<isRequest, Body, Headers>& msg)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
read(stream, streambuf, msg, ec);
|
read(stream, streambuf, msg, ec);
|
||||||
@ -61,7 +61,7 @@ template<class SyncReadStream, class Streambuf,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& msg,
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start reading a HTTP message from a stream asynchronously.
|
/** Start reading a HTTP message from a stream asynchronously.
|
||||||
@ -97,7 +97,7 @@ typename async_completion<
|
|||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
||||||
message<isRequest, Body, Headers>& msg,
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
ReadHandler&& handler);
|
ReadHandler&& handler);
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_STREAMBUF_BODY_HPP
|
#ifndef BEAST_HTTP_STREAMBUF_BODY_HPP
|
||||||
#define BEAST_HTTP_STREAMBUF_BODY_HPP
|
#define BEAST_HTTP_STREAMBUF_BODY_HPP
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/body_writer.hpp>
|
||||||
#include <beast/http/message.hpp>
|
|
||||||
#include <beast/buffer_cat.hpp>
|
#include <beast/buffer_cat.hpp>
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -59,10 +58,13 @@ private:
|
|||||||
Streambuf const& body_;
|
Streambuf const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<bool isRequest, class Allocator>
|
writer(writer const&) = delete;
|
||||||
|
writer& operator=(writer const&) = delete;
|
||||||
|
|
||||||
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, basic_streambuf_body,
|
writer(message<
|
||||||
Allocator> const& m)
|
isRequest, basic_streambuf_body, Headers> const& m)
|
||||||
: body_(m.body)
|
: body_(m.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_STRING_BODY_HPP
|
#ifndef BEAST_HTTP_STRING_BODY_HPP
|
||||||
#define BEAST_HTTP_STRING_BODY_HPP
|
#define BEAST_HTTP_STRING_BODY_HPP
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/body_writer.hpp>
|
||||||
#include <beast/http/message.hpp>
|
|
||||||
#include <beast/http/resume_context.hpp>
|
|
||||||
#include <beast/buffer_cat.hpp>
|
#include <beast/buffer_cat.hpp>
|
||||||
#include <beast/streambuf.hpp>
|
#include <beast/streambuf.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -58,9 +56,13 @@ private:
|
|||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<bool isRequest, class Allocator>
|
writer(writer const&) = delete;
|
||||||
|
writer& operator=(writer const&) = delete;
|
||||||
|
|
||||||
|
template<bool isRequest, class Headers>
|
||||||
explicit
|
explicit
|
||||||
writer(message<isRequest, string_body, Allocator> const& msg)
|
writer(message<
|
||||||
|
isRequest, string_body, Headers> const& msg)
|
||||||
: body_(msg.body)
|
: body_(msg.body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,8 @@
|
|||||||
#define BEAST_HTTP_WRITE_HPP
|
#define BEAST_HTTP_WRITE_HPP
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
#include <beast/http/error.hpp>
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/async_completion.hpp>
|
#include <beast/async_completion.hpp>
|
||||||
#include <beast/type_check.hpp>
|
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@ -19,7 +18,7 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/** Write a HTTP message to a stream.
|
/** Write a HTTP/1 message to a stream.
|
||||||
|
|
||||||
@param stream The stream to send the message on.
|
@param stream The stream to send the message on.
|
||||||
|
|
||||||
@ -31,15 +30,9 @@ template<class SyncWriteStream,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(SyncWriteStream& stream,
|
write(SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg)
|
message_v1<isRequest, Body, Headers> const& msg);
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
write(stream, msg, ec);
|
|
||||||
if(ec)
|
|
||||||
throw boost::system::system_error{ec};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Write a HTTP message to a stream.
|
/** Write a HTTP/1 message to a stream.
|
||||||
|
|
||||||
@param stream The stream to send the message on.
|
@param stream The stream to send the message on.
|
||||||
|
|
||||||
@ -51,10 +44,10 @@ template<class SyncWriteStream,
|
|||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write(SyncWriteStream& stream,
|
write(SyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start writing a HTTP message to a stream asynchronously.
|
/** Start writing a HTTP/1 message to a stream asynchronously.
|
||||||
|
|
||||||
@param stream The stream to send the message on.
|
@param stream The stream to send the message on.
|
||||||
|
|
||||||
@ -84,12 +77,12 @@ typename async_completion<
|
|||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_write(AsyncWriteStream& stream,
|
async_write(AsyncWriteStream& stream,
|
||||||
message<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
/** Serialize a message to an ostream.
|
/** Serialize a HTTP/1 message to an ostream.
|
||||||
|
|
||||||
The function converts the message to its HTTP/1.* serialized
|
The function converts the message to its HTTP/1 serialized
|
||||||
representation and stores the result in the output stream.
|
representation and stores the result in the output stream.
|
||||||
|
|
||||||
@param os The ostream to write to.
|
@param os The ostream to write to.
|
||||||
@ -99,7 +92,7 @@ async_write(AsyncWriteStream& stream,
|
|||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<<(std::ostream& os,
|
operator<<(std::ostream& os,
|
||||||
message<isRequest, Body, Headers> const& msg);
|
message_v1<isRequest, Body, Headers> const& msg);
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
@ -9,10 +9,11 @@
|
|||||||
#define BEAST_WEBSOCKET_IMPL_ACCEPT_OP_HPP
|
#define BEAST_WEBSOCKET_IMPL_ACCEPT_OP_HPP
|
||||||
|
|
||||||
#include <beast/websocket/impl/response_op.ipp>
|
#include <beast/websocket/impl/response_op.ipp>
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
|
#include <beast/http/parser_v1.hpp>
|
||||||
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
#include <beast/prepare_buffers.hpp>
|
#include <beast/prepare_buffers.hpp>
|
||||||
#include <beast/http/parser.hpp>
|
|
||||||
#include <beast/http/read.hpp>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@ -32,7 +33,7 @@ class stream<NextLayer>::accept_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
http::request<http::empty_body> req;
|
http::request_v1<http::empty_body> req;
|
||||||
Handler h;
|
Handler h;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
#include <beast/http/empty_body.hpp>
|
#include <beast/http/empty_body.hpp>
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -33,8 +33,8 @@ class stream<NextLayer>::handshake_op
|
|||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
Handler h;
|
Handler h;
|
||||||
std::string key;
|
std::string key;
|
||||||
http::request<http::empty_body> req;
|
http::request_v1<http::empty_body> req;
|
||||||
http::response<http::string_body> resp;
|
http::response_v1<http::string_body> resp;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP
|
#define BEAST_WEBSOCKET_IMPL_RESPONSE_OP_HPP
|
||||||
|
|
||||||
#include <beast/handler_alloc.hpp>
|
#include <beast/handler_alloc.hpp>
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/http/string_body.hpp>
|
#include <beast/http/string_body.hpp>
|
||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -27,7 +28,7 @@ class stream<NextLayer>::response_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
http::response<http::string_body> resp;
|
http::response_v1<http::string_body> resp;
|
||||||
Handler h;
|
Handler h;
|
||||||
error_code final_ec;
|
error_code final_ec;
|
||||||
bool cont;
|
bool cont;
|
||||||
@ -36,7 +37,7 @@ class stream<NextLayer>::response_op
|
|||||||
template<class DeducedHandler,
|
template<class DeducedHandler,
|
||||||
class Body, class Headers>
|
class Body, class Headers>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
||||||
http::message<true, Body, Headers> const& req,
|
http::request_v1<Body, Headers> const& req,
|
||||||
bool cont_)
|
bool cont_)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
, resp(ws_.build_response(req))
|
, resp(ws_.build_response(req))
|
||||||
|
@ -241,7 +241,7 @@ accept(ConstBufferSequence const& buffers, error_code& ec)
|
|||||||
stream_.buffer().commit(buffer_copy(
|
stream_.buffer().commit(buffer_copy(
|
||||||
stream_.buffer().prepare(
|
stream_.buffer().prepare(
|
||||||
buffer_size(buffers)), buffers));
|
buffer_size(buffers)), buffers));
|
||||||
http::request<http::empty_body> m;
|
http::request_v1<http::empty_body> m;
|
||||||
http::read(next_layer(), stream_.buffer(), m, ec);
|
http::read(next_layer(), stream_.buffer(), m, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
@ -272,7 +272,7 @@ template<class NextLayer>
|
|||||||
template<class Body, class Headers>
|
template<class Body, class Headers>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept(http::message<true, Body, Headers> const& request)
|
accept(http::request_v1<Body, Headers> const& request)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_SyncStream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
@ -285,12 +285,12 @@ template<class NextLayer>
|
|||||||
template<class Body, class Headers>
|
template<class Body, class Headers>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
accept(http::message<true, Body, Headers> const& req,
|
accept(http::request_v1<Body, Headers> const& req,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_SyncStream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
auto resp = build_response(req);
|
auto const resp = build_response(req);
|
||||||
http::write(stream_, resp, ec);
|
http::write(stream_, resp, ec);
|
||||||
if(resp.status != 101)
|
if(resp.status != 101)
|
||||||
{
|
{
|
||||||
@ -307,7 +307,7 @@ template<class Body, class Headers, class AcceptHandler>
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
AcceptHandler, void(error_code)>::result_type
|
AcceptHandler, void(error_code)>::result_type
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
async_accept(http::message<true, Body, Headers> const& req,
|
async_accept(http::request_v1<Body, Headers> const& req,
|
||||||
AcceptHandler&& handler)
|
AcceptHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||||
@ -348,7 +348,7 @@ handshake(boost::string_ref const& host,
|
|||||||
build_request(host, resource, key), ec);
|
build_request(host, resource, key), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
http::response<http::string_body> resp;
|
http::response_v1<http::string_body> resp;
|
||||||
http::read(next_layer(), stream_.buffer(), resp, ec);
|
http::read(next_layer(), stream_.buffer(), resp, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
@ -826,12 +826,12 @@ async_write_frame(bool fin,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
http::request<http::empty_body>
|
http::request_v1<http::empty_body>
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
build_request(boost::string_ref const& host,
|
build_request(boost::string_ref const& host,
|
||||||
boost::string_ref const& resource, std::string& key)
|
boost::string_ref const& resource, std::string& key)
|
||||||
{
|
{
|
||||||
http::request<http::empty_body> req;
|
http::request_v1<http::empty_body> req;
|
||||||
req.url = "/";
|
req.url = "/";
|
||||||
req.version = 11;
|
req.version = 11;
|
||||||
req.method = "GET";
|
req.method = "GET";
|
||||||
@ -847,14 +847,14 @@ build_request(boost::string_ref const& host,
|
|||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Body, class Headers>
|
template<class Body, class Headers>
|
||||||
http::response<http::string_body>
|
http::response_v1<http::string_body>
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
build_response(http::message<true, Body, Headers> const& req)
|
build_response(http::request_v1<Body, Headers> const& req)
|
||||||
{
|
{
|
||||||
auto err =
|
auto err =
|
||||||
[&](std::string const& text)
|
[&](std::string const& text)
|
||||||
{
|
{
|
||||||
http::response<http::string_body> resp(
|
http::response_v1<http::string_body> resp(
|
||||||
{400, http::reason_string(400), req.version});
|
{400, http::reason_string(400), req.version});
|
||||||
resp.body = text;
|
resp.body = text;
|
||||||
// VFALCO TODO respect keep-alive here
|
// VFALCO TODO respect keep-alive here
|
||||||
@ -881,7 +881,7 @@ build_response(http::message<true, Body, Headers> const& req)
|
|||||||
if(! rfc2616::token_in_list(
|
if(! rfc2616::token_in_list(
|
||||||
req.headers["Upgrade"], "websocket"))
|
req.headers["Upgrade"], "websocket"))
|
||||||
return err("Missing websocket Upgrade token");
|
return err("Missing websocket Upgrade token");
|
||||||
http::response<http::string_body> resp(
|
http::response_v1<http::string_body> resp(
|
||||||
{101, http::reason_string(101), req.version});
|
{101, http::reason_string(101), req.version});
|
||||||
resp.headers.insert("Upgrade", "websocket");
|
resp.headers.insert("Upgrade", "websocket");
|
||||||
{
|
{
|
||||||
@ -901,7 +901,7 @@ template<class NextLayer>
|
|||||||
template<class Body, class Headers>
|
template<class Body, class Headers>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
do_response(http::message<false, Body, Headers> const& resp,
|
do_response(http::response_v1<Body, Headers> const& resp,
|
||||||
boost::string_ref const& key, error_code& ec)
|
boost::string_ref const& key, error_code& ec)
|
||||||
{
|
{
|
||||||
// VFALCO Review these error codes
|
// VFALCO Review these error codes
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
|
|
||||||
#include <beast/websocket/option.hpp>
|
#include <beast/websocket/option.hpp>
|
||||||
#include <beast/websocket/detail/stream_base.hpp>
|
#include <beast/websocket/detail/stream_base.hpp>
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
|
#include <beast/http/string_body.hpp>
|
||||||
#include <beast/streambuf_readstream.hpp>
|
#include <beast/streambuf_readstream.hpp>
|
||||||
#include <beast/async_completion.hpp>
|
#include <beast/async_completion.hpp>
|
||||||
#include <beast/detail/get_lowest_layer.hpp>
|
#include <beast/detail/get_lowest_layer.hpp>
|
||||||
#include <beast/http/message.hpp>
|
|
||||||
#include <beast/http/string_body.hpp>
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/utility/string_ref.hpp>
|
#include <boost/utility/string_ref.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -495,8 +495,7 @@ public:
|
|||||||
// VFALCO TODO This should also take a streambuf with any leftover bytes.
|
// VFALCO TODO This should also take a streambuf with any leftover bytes.
|
||||||
template<class Body, class Headers>
|
template<class Body, class Headers>
|
||||||
void
|
void
|
||||||
accept(http::message<true,
|
accept(http::request_v1<Body, Headers> const& request);
|
||||||
Body, Headers> const& request);
|
|
||||||
|
|
||||||
/** Respond to a WebSocket HTTP Upgrade request
|
/** Respond to a WebSocket HTTP Upgrade request
|
||||||
|
|
||||||
@ -525,8 +524,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<class Body, class Headers>
|
template<class Body, class Headers>
|
||||||
void
|
void
|
||||||
accept(http::message<true,
|
accept(http::request_v1<Body, Headers> const& request,
|
||||||
Body, Headers> const& request, error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start reading and responding to a WebSocket HTTP Upgrade request.
|
/** Start reading and responding to a WebSocket HTTP Upgrade request.
|
||||||
|
|
||||||
@ -560,8 +559,8 @@ public:
|
|||||||
template<class Body, class Headers, class AcceptHandler>
|
template<class Body, class Headers, class AcceptHandler>
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
AcceptHandler, void(error_code)>::result_type
|
AcceptHandler, void(error_code)>::result_type
|
||||||
async_accept(http::message<true,
|
async_accept(http::request_v1<Body, Headers> const& request,
|
||||||
Body, Headers> const& request, AcceptHandler&& handler);
|
AcceptHandler&& handler);
|
||||||
|
|
||||||
/** Send a WebSocket Upgrade request.
|
/** Send a WebSocket Upgrade request.
|
||||||
|
|
||||||
@ -1129,18 +1128,18 @@ private:
|
|||||||
template<class Buffers, class Handler> class write_op;
|
template<class Buffers, class Handler> class write_op;
|
||||||
template<class Buffers, class Handler> class write_frame_op;
|
template<class Buffers, class Handler> class write_frame_op;
|
||||||
|
|
||||||
http::request<http::empty_body>
|
http::request_v1<http::empty_body>
|
||||||
build_request(boost::string_ref const& host,
|
build_request(boost::string_ref const& host,
|
||||||
boost::string_ref const& resource,
|
boost::string_ref const& resource,
|
||||||
std::string& key);
|
std::string& key);
|
||||||
|
|
||||||
template<class Body, class Headers>
|
template<class Body, class Headers>
|
||||||
http::response<http::string_body>
|
http::response_v1<http::string_body>
|
||||||
build_response(http::message<true, Body, Headers> const& req);
|
build_response(http::request_v1<Body, Headers> const& req);
|
||||||
|
|
||||||
template<class Body, class Headers>
|
template<class Body, class Headers>
|
||||||
void
|
void
|
||||||
do_response(http::message<false, Body, Headers> const& resp,
|
do_response(http::response_v1<Body, Headers> const& resp,
|
||||||
boost::string_ref const& key, error_code& ec);
|
boost::string_ref const& key, error_code& ec);
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -33,11 +33,12 @@ add_executable (http-tests
|
|||||||
${BEAST_INCLUDES}
|
${BEAST_INCLUDES}
|
||||||
main.cpp
|
main.cpp
|
||||||
http/basic_headers.cpp
|
http/basic_headers.cpp
|
||||||
http/basic_parser.cpp
|
http/basic_parser_v1.cpp
|
||||||
http/empty_body.cpp
|
http/empty_body.cpp
|
||||||
http/error.cpp
|
http/error.cpp
|
||||||
http/headers.cpp
|
http/headers.cpp
|
||||||
http/message.cpp
|
http/message.cpp
|
||||||
|
http/message_v1.cpp
|
||||||
http/parse_error.cpp
|
http/parse_error.cpp
|
||||||
http/parser.cpp
|
http/parser.cpp
|
||||||
http/read.cpp
|
http/read.cpp
|
||||||
|
@ -31,11 +31,12 @@ unit-test core-tests :
|
|||||||
unit-test http-tests :
|
unit-test http-tests :
|
||||||
main.cpp
|
main.cpp
|
||||||
http/basic_headers.cpp
|
http/basic_headers.cpp
|
||||||
http/basic_parser.cpp
|
http/basic_parser_v1.cpp
|
||||||
http/empty_body.cpp
|
http/empty_body.cpp
|
||||||
http/error.cpp
|
http/error.cpp
|
||||||
http/headers.cpp
|
http/headers.cpp
|
||||||
http/message.cpp
|
http/message.cpp
|
||||||
|
http/message_v1.cpp
|
||||||
http/parse_error.cpp
|
http/parse_error.cpp
|
||||||
http/parser.cpp
|
http/parser.cpp
|
||||||
http/read.cpp
|
http/read.cpp
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/http/basic_parser.hpp>
|
#include <beast/http/basic_parser_v1.hpp>
|
||||||
|
|
||||||
#include "message_fuzz.hpp"
|
#include "message_fuzz.hpp"
|
||||||
|
|
||||||
@ -27,7 +27,7 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
class basic_parser_test : public beast::detail::unit_test::suite
|
class basic_parser_v1_test : public beast::detail::unit_test::suite
|
||||||
{
|
{
|
||||||
std::mt19937 rng_;
|
std::mt19937 rng_;
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest>
|
template<bool isRequest>
|
||||||
struct cb_checker
|
struct cb_checker
|
||||||
: public basic_parser<isRequest, cb_checker<isRequest>>
|
: public basic_parser_v1<isRequest, cb_checker<isRequest>>
|
||||||
, std::conditional<isRequest,
|
, std::conditional<isRequest,
|
||||||
cb_req_checker, cb_res_checker>::type
|
cb_req_checker, cb_res_checker>::type
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ public:
|
|||||||
bool complete = false;
|
bool complete = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class basic_parser<isRequest, cb_checker<isRequest>>;
|
friend class basic_parser_v1<isRequest, cb_checker<isRequest>>;
|
||||||
|
|
||||||
void on_method(boost::string_ref const&, error_code&)
|
void on_method(boost::string_ref const&, error_code&)
|
||||||
{
|
{
|
||||||
@ -129,13 +129,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest>
|
template<bool isRequest>
|
||||||
struct null_parser : basic_parser<isRequest, null_parser<isRequest>>
|
struct null_parser : basic_parser_v1<isRequest, null_parser<isRequest>>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template<bool isRequest>
|
template<bool isRequest>
|
||||||
class test_parser :
|
class test_parser :
|
||||||
public basic_parser<isRequest, test_parser<isRequest>>
|
public basic_parser_v1<isRequest, test_parser<isRequest>>
|
||||||
{
|
{
|
||||||
std::string field_;
|
std::string field_;
|
||||||
std::string value_;
|
std::string value_;
|
||||||
@ -635,7 +635,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(basic_parser,http,beast);
|
BEAST_DEFINE_TESTSUITE(basic_parser_v1,http,beast);
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
@ -19,168 +19,3 @@
|
|||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message.hpp>
|
||||||
|
|
||||||
#include <beast/detail/unit_test/suite.hpp>
|
|
||||||
#include <beast/detail/unit_test/thread.hpp>
|
|
||||||
#include <beast/placeholders.hpp>
|
|
||||||
#include <beast/streambuf.hpp>
|
|
||||||
#include <beast/http.hpp>
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
class sync_echo_http_server
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using error_code = boost::system::error_code;
|
|
||||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
|
||||||
using address_type = boost::asio::ip::address;
|
|
||||||
using socket_type = boost::asio::ip::tcp::socket;
|
|
||||||
|
|
||||||
private:
|
|
||||||
beast::detail::unit_test::suite& suite_;
|
|
||||||
boost::asio::io_service ios_;
|
|
||||||
socket_type sock_;
|
|
||||||
boost::asio::ip::tcp::acceptor acceptor_;
|
|
||||||
beast::detail::unit_test::thread thread_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
sync_echo_http_server(
|
|
||||||
endpoint_type ep, beast::detail::unit_test::suite& suite)
|
|
||||||
: suite_(suite)
|
|
||||||
, sock_(ios_)
|
|
||||||
, acceptor_(ios_)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
acceptor_.open(ep.protocol(), ec);
|
|
||||||
maybe_throw(ec, "open");
|
|
||||||
acceptor_.bind(ep, ec);
|
|
||||||
maybe_throw(ec, "bind");
|
|
||||||
acceptor_.listen(
|
|
||||||
boost::asio::socket_base::max_connections, ec);
|
|
||||||
maybe_throw(ec, "listen");
|
|
||||||
acceptor_.async_accept(sock_,
|
|
||||||
std::bind(&sync_echo_http_server::on_accept, this,
|
|
||||||
beast::asio::placeholders::error));
|
|
||||||
thread_ = beast::detail::unit_test::thread(suite_,
|
|
||||||
[&]
|
|
||||||
{
|
|
||||||
ios_.run();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
~sync_echo_http_server()
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
ios_.dispatch(
|
|
||||||
[&]{ acceptor_.close(ec); });
|
|
||||||
thread_.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void
|
|
||||||
fail(error_code ec, std::string what)
|
|
||||||
{
|
|
||||||
suite_.log <<
|
|
||||||
what << ": " << ec.message();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
maybe_throw(error_code ec, std::string what)
|
|
||||||
{
|
|
||||||
if(ec &&
|
|
||||||
ec != boost::asio::error::operation_aborted)
|
|
||||||
{
|
|
||||||
fail(ec, what);
|
|
||||||
throw ec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
on_accept(error_code ec)
|
|
||||||
{
|
|
||||||
if(ec == boost::asio::error::operation_aborted)
|
|
||||||
return;
|
|
||||||
maybe_throw(ec, "accept");
|
|
||||||
std::thread{&sync_echo_http_server::do_client, this,
|
|
||||||
std::move(sock_), boost::asio::io_service::work{
|
|
||||||
sock_.get_io_service()}}.detach();
|
|
||||||
acceptor_.async_accept(sock_,
|
|
||||||
std::bind(&sync_echo_http_server::on_accept, this,
|
|
||||||
beast::asio::placeholders::error));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
do_client(socket_type sock, boost::asio::io_service::work)
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
streambuf rb;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
request<string_body> req;
|
|
||||||
read(sock, rb, req, ec);
|
|
||||||
if(ec)
|
|
||||||
break;
|
|
||||||
response<string_body> resp(
|
|
||||||
{100, "OK", req.version});
|
|
||||||
resp.body = "Completed successfully.";
|
|
||||||
write(sock, resp, ec);
|
|
||||||
if(ec)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class message_test : public beast::detail::unit_test::suite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using error_code = boost::system::error_code;
|
|
||||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
|
||||||
using address_type = boost::asio::ip::address;
|
|
||||||
using socket_type = boost::asio::ip::tcp::socket;
|
|
||||||
|
|
||||||
void
|
|
||||||
syncEcho(endpoint_type ep)
|
|
||||||
{
|
|
||||||
boost::asio::io_service ios;
|
|
||||||
socket_type sock(ios);
|
|
||||||
sock.connect(ep);
|
|
||||||
|
|
||||||
streambuf rb;
|
|
||||||
{
|
|
||||||
request<string_body> req({"GET", "/", 11});
|
|
||||||
req.body = "Beast.HTTP";
|
|
||||||
req.headers.replace("Host",
|
|
||||||
ep.address().to_string() + ":" +
|
|
||||||
std::to_string(ep.port()));
|
|
||||||
write(sock, req);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
response<string_body> m;
|
|
||||||
read(sock, rb, m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
testAsio()
|
|
||||||
{
|
|
||||||
endpoint_type ep{
|
|
||||||
address_type::from_string("127.0.0.1"), 6000};
|
|
||||||
sync_echo_http_server s(ep, *this);
|
|
||||||
syncEcho(ep);
|
|
||||||
}
|
|
||||||
|
|
||||||
void run() override
|
|
||||||
{
|
|
||||||
testAsio();
|
|
||||||
pass();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(message,http,beast);
|
|
||||||
|
|
||||||
} // test
|
|
||||||
} // http
|
|
||||||
} // beast
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
|
#ifndef BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
|
||||||
#define BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
|
#define BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
|
||||||
|
|
||||||
#include <beast/http/detail/basic_parser.hpp>
|
#include <beast/http/detail/basic_parser_v1.hpp>
|
||||||
#include <beast/write_streambuf.hpp>
|
#include <beast/write_streambuf.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
186
test/http/message_v1.cpp
Normal file
186
test/http/message_v1.cpp
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||||
|
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
// Test that header file is self-contained.
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
|
|
||||||
|
#include <beast/detail/unit_test/suite.hpp>
|
||||||
|
#include <beast/detail/unit_test/thread.hpp>
|
||||||
|
#include <beast/placeholders.hpp>
|
||||||
|
#include <beast/streambuf.hpp>
|
||||||
|
#include <beast/http.hpp>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
namespace test {
|
||||||
|
|
||||||
|
class sync_echo_http_server
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using error_code = boost::system::error_code;
|
||||||
|
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||||
|
using address_type = boost::asio::ip::address;
|
||||||
|
using socket_type = boost::asio::ip::tcp::socket;
|
||||||
|
|
||||||
|
private:
|
||||||
|
beast::detail::unit_test::suite& suite_;
|
||||||
|
boost::asio::io_service ios_;
|
||||||
|
socket_type sock_;
|
||||||
|
boost::asio::ip::tcp::acceptor acceptor_;
|
||||||
|
beast::detail::unit_test::thread thread_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
sync_echo_http_server(
|
||||||
|
endpoint_type ep, beast::detail::unit_test::suite& suite)
|
||||||
|
: suite_(suite)
|
||||||
|
, sock_(ios_)
|
||||||
|
, acceptor_(ios_)
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
acceptor_.open(ep.protocol(), ec);
|
||||||
|
maybe_throw(ec, "open");
|
||||||
|
acceptor_.bind(ep, ec);
|
||||||
|
maybe_throw(ec, "bind");
|
||||||
|
acceptor_.listen(
|
||||||
|
boost::asio::socket_base::max_connections, ec);
|
||||||
|
maybe_throw(ec, "listen");
|
||||||
|
acceptor_.async_accept(sock_,
|
||||||
|
std::bind(&sync_echo_http_server::on_accept, this,
|
||||||
|
beast::asio::placeholders::error));
|
||||||
|
thread_ = beast::detail::unit_test::thread(suite_,
|
||||||
|
[&]
|
||||||
|
{
|
||||||
|
ios_.run();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
~sync_echo_http_server()
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
ios_.dispatch(
|
||||||
|
[&]{ acceptor_.close(ec); });
|
||||||
|
thread_.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void
|
||||||
|
fail(error_code ec, std::string what)
|
||||||
|
{
|
||||||
|
suite_.log <<
|
||||||
|
what << ": " << ec.message();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
maybe_throw(error_code ec, std::string what)
|
||||||
|
{
|
||||||
|
if(ec &&
|
||||||
|
ec != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
fail(ec, what);
|
||||||
|
throw ec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
on_accept(error_code ec)
|
||||||
|
{
|
||||||
|
if(ec == boost::asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
maybe_throw(ec, "accept");
|
||||||
|
std::thread{&sync_echo_http_server::do_client, this,
|
||||||
|
std::move(sock_), boost::asio::io_service::work{
|
||||||
|
sock_.get_io_service()}}.detach();
|
||||||
|
acceptor_.async_accept(sock_,
|
||||||
|
std::bind(&sync_echo_http_server::on_accept, this,
|
||||||
|
beast::asio::placeholders::error));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
do_client(socket_type sock, boost::asio::io_service::work)
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
streambuf rb;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
request_v1<string_body> req;
|
||||||
|
read(sock, rb, req, ec);
|
||||||
|
if(ec)
|
||||||
|
break;
|
||||||
|
response_v1<string_body> resp(
|
||||||
|
{100, "OK", req.version});
|
||||||
|
resp.body = "Completed successfully.";
|
||||||
|
write(sock, resp, ec);
|
||||||
|
if(ec)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class message_test : public beast::detail::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using error_code = boost::system::error_code;
|
||||||
|
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||||
|
using address_type = boost::asio::ip::address;
|
||||||
|
using socket_type = boost::asio::ip::tcp::socket;
|
||||||
|
|
||||||
|
void
|
||||||
|
syncEcho(endpoint_type ep)
|
||||||
|
{
|
||||||
|
boost::asio::io_service ios;
|
||||||
|
socket_type sock(ios);
|
||||||
|
sock.connect(ep);
|
||||||
|
|
||||||
|
streambuf rb;
|
||||||
|
{
|
||||||
|
request_v1<string_body> req({"GET", "/", 11});
|
||||||
|
req.body = "Beast.HTTP";
|
||||||
|
req.headers.replace("Host",
|
||||||
|
ep.address().to_string() + ":" +
|
||||||
|
std::to_string(ep.port()));
|
||||||
|
write(sock, req);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
response_v1<string_body> m;
|
||||||
|
read(sock, rb, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testAsio()
|
||||||
|
{
|
||||||
|
endpoint_type ep{
|
||||||
|
address_type::from_string("127.0.0.1"), 6000};
|
||||||
|
sync_echo_http_server s(ep, *this);
|
||||||
|
syncEcho(ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
testAsio();
|
||||||
|
pass();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(message,http,beast);
|
||||||
|
|
||||||
|
} // test
|
||||||
|
} // http
|
||||||
|
} // beast
|
@ -10,7 +10,8 @@
|
|||||||
|
|
||||||
#include "nodejs-parser/http_parser.h"
|
#include "nodejs-parser/http_parser.h"
|
||||||
|
|
||||||
#include <beast/http/basic_parser.hpp>
|
#include <beast/http/error.hpp>
|
||||||
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/http/rfc2616.hpp>
|
#include <beast/http/rfc2616.hpp>
|
||||||
#include <beast/type_check.hpp>
|
#include <beast/type_check.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
@ -18,6 +19,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
@ -730,19 +732,6 @@ nodejs_basic_parser<Derived>::cb_chunk_complete(http_parser*)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // http
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#include <beast/http/error.hpp>
|
|
||||||
#include <beast/http/message.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <functional>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
/** A HTTP parser.
|
/** A HTTP parser.
|
||||||
|
|
||||||
The parser may only be used once.
|
The parser may only be used once.
|
||||||
@ -752,7 +741,7 @@ class nodejs_parser
|
|||||||
: public nodejs_basic_parser<nodejs_parser<isRequest, Body, Headers>>
|
: public nodejs_basic_parser<nodejs_parser<isRequest, Body, Headers>>
|
||||||
{
|
{
|
||||||
using message_type =
|
using message_type =
|
||||||
message<isRequest, Body, Headers>;
|
message_v1<isRequest, Body, Headers>;
|
||||||
|
|
||||||
message_type m_;
|
message_type m_;
|
||||||
typename message_type::body_type::reader r_;
|
typename message_type::body_type::reader r_;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/http/parser.hpp>
|
#include <beast/http/parser_v1.hpp>
|
||||||
|
|
||||||
#include <beast/http/headers.hpp>
|
#include <beast/http/headers.hpp>
|
||||||
#include <beast/http/string_body.hpp>
|
#include <beast/http/string_body.hpp>
|
||||||
@ -23,7 +23,7 @@ public:
|
|||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
parser<true, string_body,
|
parser_v1<true, string_body,
|
||||||
basic_headers<std::allocator<char>>> p;
|
basic_headers<std::allocator<char>>> p;
|
||||||
std::string const s =
|
std::string const s =
|
||||||
"GET / HTTP/1.1\r\n"
|
"GET / HTTP/1.1\r\n"
|
||||||
@ -43,7 +43,7 @@ public:
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
parser<false, string_body,
|
parser_v1<false, string_body,
|
||||||
basic_headers<std::allocator<char>>> p;
|
basic_headers<std::allocator<char>>> p;
|
||||||
std::string const s =
|
std::string const s =
|
||||||
"HTTP/1.1 200 OK\r\n"
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
@ -97,7 +97,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest>
|
template<bool isRequest>
|
||||||
struct null_parser : basic_parser<isRequest, null_parser<isRequest>>
|
struct null_parser : basic_parser_v1<isRequest, null_parser<isRequest>>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,10 +108,10 @@ public:
|
|||||||
static std::size_t constexpr Repeat = 50;
|
static std::size_t constexpr Repeat = 50;
|
||||||
|
|
||||||
log << "sizeof(request parser) == " <<
|
log << "sizeof(request parser) == " <<
|
||||||
sizeof(basic_parser<true, null_parser<true>>);
|
sizeof(basic_parser_v1<true, null_parser<true>>);
|
||||||
|
|
||||||
log << "sizeof(response parser) == " <<
|
log << "sizeof(response parser) == " <<
|
||||||
sizeof(basic_parser<false, null_parser<true>>);
|
sizeof(basic_parser_v1<false, null_parser<true>>);
|
||||||
|
|
||||||
testcase << "Parser speed test, " <<
|
testcase << "Parser speed test, " <<
|
||||||
((Repeat * size_ + 512) / 1024) << "KB in " <<
|
((Repeat * size_ + 512) / 1024) << "KB in " <<
|
||||||
@ -127,13 +127,13 @@ public:
|
|||||||
false, streambuf_body, headers>>(
|
false, streambuf_body, headers>>(
|
||||||
Repeat, cres_);
|
Repeat, cres_);
|
||||||
});
|
});
|
||||||
timedTest(Trials, "http::basic_parser",
|
timedTest(Trials, "http::basic_parser_v1",
|
||||||
[&]
|
[&]
|
||||||
{
|
{
|
||||||
testParser<parser<
|
testParser<parser_v1<
|
||||||
true, streambuf_body, headers>>(
|
true, streambuf_body, headers>>(
|
||||||
Repeat, creq_);
|
Repeat, creq_);
|
||||||
testParser<parser<
|
testParser<parser_v1<
|
||||||
false, streambuf_body, headers>>(
|
false, streambuf_body, headers>>(
|
||||||
Repeat, cres_);
|
Repeat, cres_);
|
||||||
});
|
});
|
||||||
|
@ -89,7 +89,7 @@ public:
|
|||||||
|
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
std::string
|
std::string
|
||||||
str(message<isRequest, Body, Headers> const& m)
|
str(message_v1<isRequest, Body, Headers> const& m)
|
||||||
{
|
{
|
||||||
string_SyncStream ss;
|
string_SyncStream ss;
|
||||||
write(ss, m);
|
write(ss, m);
|
||||||
@ -101,7 +101,7 @@ public:
|
|||||||
{
|
{
|
||||||
// auto content-length HTTP/1.0
|
// auto content-length HTTP/1.0
|
||||||
{
|
{
|
||||||
message<true, string_body, headers> m{{
|
message_v1<true, string_body, headers> m{{
|
||||||
"GET", "/", 10}};
|
"GET", "/", 10}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
@ -116,7 +116,7 @@ public:
|
|||||||
}
|
}
|
||||||
// keep-alive HTTP/1.0
|
// keep-alive HTTP/1.0
|
||||||
{
|
{
|
||||||
message<true, string_body, headers> m{{
|
message_v1<true, string_body, headers> m{{
|
||||||
"GET", "/", 10}};
|
"GET", "/", 10}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
@ -132,7 +132,7 @@ public:
|
|||||||
}
|
}
|
||||||
// upgrade HTTP/1.0
|
// upgrade HTTP/1.0
|
||||||
{
|
{
|
||||||
message<true, string_body, headers> m{{
|
message_v1<true, string_body, headers> m{{
|
||||||
"GET", "/", 10}};
|
"GET", "/", 10}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
@ -148,7 +148,7 @@ public:
|
|||||||
}
|
}
|
||||||
// no content-length HTTP/1.0
|
// no content-length HTTP/1.0
|
||||||
{
|
{
|
||||||
message<true, test_Body, headers> m{{
|
message_v1<true, test_Body, headers> m{{
|
||||||
"GET", "/", 10}};
|
"GET", "/", 10}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
@ -166,7 +166,7 @@ public:
|
|||||||
}
|
}
|
||||||
// auto content-length HTTP/1.1
|
// auto content-length HTTP/1.1
|
||||||
{
|
{
|
||||||
message<true, string_body, headers> m{{
|
message_v1<true, string_body, headers> m{{
|
||||||
"GET", "/", 11}};
|
"GET", "/", 11}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
@ -181,7 +181,7 @@ public:
|
|||||||
}
|
}
|
||||||
// close HTTP/1.1
|
// close HTTP/1.1
|
||||||
{
|
{
|
||||||
message<true, string_body, headers> m{{
|
message_v1<true, string_body, headers> m{{
|
||||||
"GET", "/", 11}};
|
"GET", "/", 11}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
@ -201,7 +201,7 @@ public:
|
|||||||
}
|
}
|
||||||
// upgrade HTTP/1.1
|
// upgrade HTTP/1.1
|
||||||
{
|
{
|
||||||
message<true, empty_body, headers> m{{
|
message_v1<true, empty_body, headers> m{{
|
||||||
"GET", "/", 11}};
|
"GET", "/", 11}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
prepare(m, connection::upgrade);
|
prepare(m, connection::upgrade);
|
||||||
@ -214,7 +214,7 @@ public:
|
|||||||
}
|
}
|
||||||
// no content-length HTTP/1.1
|
// no content-length HTTP/1.1
|
||||||
{
|
{
|
||||||
message<true, test_Body, headers> m{{
|
message_v1<true, test_Body, headers> m{{
|
||||||
"GET", "/", 11}};
|
"GET", "/", 11}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
@ -236,7 +236,7 @@ public:
|
|||||||
|
|
||||||
void testConvert()
|
void testConvert()
|
||||||
{
|
{
|
||||||
message<true, string_body, headers> m{{
|
message_v1<true, string_body, headers> m{{
|
||||||
"GET", "/", 11}};
|
"GET", "/", 11}};
|
||||||
m.headers.insert("User-Agent", "test");
|
m.headers.insert("User-Agent", "test");
|
||||||
m.body = "*";
|
m.body = "*";
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <beast/http/parser.hpp>
|
#include <beast/http/parser_v1.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace websocket {
|
namespace websocket {
|
||||||
|
Reference in New Issue
Block a user