Refine message class hierarchy:

Two new objects, request_headers and response_headers,
represent the portion of HTTP messages excluding the body.
This commit is contained in:
Vinnie Falco
2016-10-20 17:22:36 -04:00
parent cf43f516d2
commit ada1f60e3e
31 changed files with 569 additions and 487 deletions
-1
View File
@@ -49,7 +49,6 @@ unit-test http-tests :
http/empty_body.cpp
http/headers.cpp
http/message.cpp
http/message_v1.cpp
http/parse.cpp
http/parse_error.cpp
http/parser_v1.cpp
-1
View File
@@ -18,7 +18,6 @@ add_executable (http-tests
empty_body.cpp
headers.cpp
message.cpp
message_v1.cpp
parse.cpp
parse_error.cpp
parser_v1.cpp
+139 -6
View File
@@ -8,6 +8,7 @@
// Test that header file is self-contained.
#include <beast/http/message.hpp>
#include <beast/http/empty_body.hpp>
#include <beast/http/headers.hpp>
#include <beast/http/string_body.hpp>
#include <beast/unit_test/suite.hpp>
@@ -69,7 +70,7 @@ public:
};
};
void testConstruction()
void testMessage()
{
static_assert(std::is_constructible<
message<true, default_body, headers>>::value, "");
@@ -125,10 +126,8 @@ public:
BEAST_EXPECT(! h.exists("User-Agent"));
BEAST_EXPECT(m.headers["User-Agent"] == "test");
}
}
void testSwap()
{
// swap
message<true, string_body, headers> m1;
message<true, string_body, headers> m2;
m1.url = "u";
@@ -147,9 +146,144 @@ public:
BEAST_EXPECT(m2.headers.exists("h"));
}
struct MoveHeaders
{
bool moved_to = false;
bool moved_from = false;
MoveHeaders() = default;
MoveHeaders(MoveHeaders&& other)
: moved_to(true)
{
other.moved_from = true;
}
MoveHeaders& operator=(MoveHeaders&& other)
{
return *this;
}
};
void testHeaders()
{
{
using req_type = request_headers<headers>;
static_assert(std::is_copy_constructible<req_type>::value, "");
static_assert(std::is_move_constructible<req_type>::value, "");
static_assert(std::is_copy_assignable<req_type>::value, "");
static_assert(std::is_move_assignable<req_type>::value, "");
using res_type = response_headers<headers>;
static_assert(std::is_copy_constructible<res_type>::value, "");
static_assert(std::is_move_constructible<res_type>::value, "");
static_assert(std::is_copy_assignable<res_type>::value, "");
static_assert(std::is_move_assignable<res_type>::value, "");
}
{
MoveHeaders h;
request_headers<MoveHeaders> r{std::move(h)};
BEAST_EXPECT(h.moved_from);
BEAST_EXPECT(r.headers.moved_to);
request<string_body, MoveHeaders> m{std::move(r)};
BEAST_EXPECT(r.headers.moved_from);
BEAST_EXPECT(m.headers.moved_to);
}
}
void testFreeFunctions()
{
{
request<empty_body> m;
m.method = "GET";
m.url = "/";
m.version = 11;
m.headers.insert("Upgrade", "test");
BEAST_EXPECT(! is_upgrade(m));
prepare(m, connection::upgrade);
BEAST_EXPECT(is_upgrade(m));
BEAST_EXPECT(m.headers["Connection"] == "upgrade");
m.version = 10;
BEAST_EXPECT(! is_upgrade(m));
}
}
void testPrepare()
{
request<empty_body> m;
m.version = 10;
BEAST_EXPECT(! is_upgrade(m));
m.headers.insert("Transfer-Encoding", "chunked");
try
{
prepare(m);
fail();
}
catch(std::exception const&)
{
}
m.headers.erase("Transfer-Encoding");
m.headers.insert("Content-Length", "0");
try
{
prepare(m);
fail();
}
catch(std::exception const&)
{
pass();
}
m.headers.erase("Content-Length");
m.headers.insert("Connection", "keep-alive");
try
{
prepare(m);
fail();
}
catch(std::exception const&)
{
pass();
}
m.version = 11;
m.headers.erase("Connection");
m.headers.insert("Connection", "close");
BEAST_EXPECT(! is_keep_alive(m));
}
void testSwap()
{
message<false, string_body, headers> m1;
message<false, string_body, headers> m2;
m1.status = 200;
m1.version = 10;
m1.body = "1";
m1.headers.insert("h", "v");
m2.status = 404;
m2.reason = "OK";
m2.body = "2";
m2.version = 11;
swap(m1, m2);
BEAST_EXPECT(m1.status == 404);
BEAST_EXPECT(m2.status == 200);
BEAST_EXPECT(m1.reason == "OK");
BEAST_EXPECT(m2.reason.empty());
BEAST_EXPECT(m1.version == 11);
BEAST_EXPECT(m2.version == 10);
BEAST_EXPECT(m1.body == "2");
BEAST_EXPECT(m2.body == "1");
BEAST_EXPECT(! m1.headers.exists("h"));
BEAST_EXPECT(m2.headers.exists("h"));
}
void run() override
{
testConstruction();
testMessage();
testHeaders();
testFreeFunctions();
testPrepare();
testSwap();
}
};
@@ -158,4 +292,3 @@ BEAST_DEFINE_TESTSUITE(message,http,beast);
} // http
} // beast
-119
View File
@@ -1,119 +0,0 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Test that header file is self-contained.
#include <beast/http/message_v1.hpp>
#include <beast/http/headers.hpp>
#include <beast/http/string_body.hpp>
#include <beast/unit_test/suite.hpp>
#include <beast/http/empty_body.hpp>
namespace beast {
namespace http {
class message_v1_test : public beast::unit_test::suite
{
public:
void testFreeFunctions()
{
{
request_v1<empty_body> m;
m.method = "GET";
m.url = "/";
m.version = 11;
m.headers.insert("Upgrade", "test");
BEAST_EXPECT(! is_upgrade(m));
prepare(m, connection::upgrade);
BEAST_EXPECT(is_upgrade(m));
BEAST_EXPECT(m.headers["Connection"] == "upgrade");
m.version = 10;
BEAST_EXPECT(! is_upgrade(m));
}
}
void testPrepare()
{
request_v1<empty_body> m;
m.version = 10;
BEAST_EXPECT(! is_upgrade(m));
m.headers.insert("Transfer-Encoding", "chunked");
try
{
prepare(m);
fail();
}
catch(std::exception const&)
{
}
m.headers.erase("Transfer-Encoding");
m.headers.insert("Content-Length", "0");
try
{
prepare(m);
fail();
}
catch(std::exception const&)
{
pass();
}
m.headers.erase("Content-Length");
m.headers.insert("Connection", "keep-alive");
try
{
prepare(m);
fail();
}
catch(std::exception const&)
{
pass();
}
m.version = 11;
m.headers.erase("Connection");
m.headers.insert("Connection", "close");
BEAST_EXPECT(! is_keep_alive(m));
}
void testSwap()
{
message_v1<false, string_body, headers> m1;
message_v1<false, string_body, headers> m2;
m1.status = 200;
m1.version = 10;
m1.body = "1";
m1.headers.insert("h", "v");
m2.status = 404;
m2.reason = "OK";
m2.body = "2";
m2.version = 11;
swap(m1, m2);
BEAST_EXPECT(m1.status == 404);
BEAST_EXPECT(m2.status == 200);
BEAST_EXPECT(m1.reason == "OK");
BEAST_EXPECT(m2.reason.empty());
BEAST_EXPECT(m1.version == 11);
BEAST_EXPECT(m2.version == 10);
BEAST_EXPECT(m1.body == "2");
BEAST_EXPECT(m2.body == "1");
BEAST_EXPECT(! m1.headers.exists("h"));
BEAST_EXPECT(m2.headers.exists("h"));
}
void run() override
{
testFreeFunctions();
testPrepare();
testSwap();
}
};
BEAST_DEFINE_TESTSUITE(message_v1,http,beast);
} // http
} // beast
+2 -2
View File
@@ -10,7 +10,7 @@
#include "nodejs-parser/http_parser.h"
#include <beast/http/message_v1.hpp>
#include <beast/http/message.hpp>
#include <beast/http/rfc7230.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <beast/core/error.hpp>
@@ -741,7 +741,7 @@ class nodejs_parser
: public nodejs_basic_parser<nodejs_parser<isRequest, Body, Headers>>
{
using message_type =
message_v1<isRequest, Body, Headers>;
message<isRequest, Body, Headers>;
message_type m_;
typename message_type::body_type::reader r_;
+3 -3
View File
@@ -259,7 +259,7 @@ public:
"Content-Length: 0\r\n"
"\r\n"
);
request_v1<streambuf_body> m;
request<streambuf_body> m;
try
{
streambuf sb;
@@ -281,7 +281,7 @@ public:
"Content-Length: 0\r\n"
"\r\n"
);
request_v1<streambuf_body> m;
request<streambuf_body> m;
error_code ec;
streambuf sb;
read(fs, sb, m, ec);
@@ -299,7 +299,7 @@ public:
"Content-Length: 0\r\n"
"\r\n"
);
request_v1<streambuf_body> m;
request<streambuf_body> m;
error_code ec;
streambuf sb;
async_read(fs, sb, m, do_yield[ec]);
+18 -18
View File
@@ -222,7 +222,7 @@ public:
template<bool isRequest, class Body, class Headers>
std::string
str(message_v1<isRequest, Body, Headers> const& m)
str(message<isRequest, Body, Headers> const& m)
{
string_write_stream ss(ios_);
write(ss, m);
@@ -233,7 +233,7 @@ public:
testAsyncWrite(yield_context do_yield)
{
{
message_v1<false, string_body, headers> m;
message<false, string_body, headers> m;
m.version = 10;
m.status = 200;
m.reason = "OK";
@@ -252,7 +252,7 @@ public:
"*****");
}
{
message_v1<false, string_body, headers> m;
message<false, string_body, headers> m;
m.version = 11;
m.status = 200;
m.reason = "OK";
@@ -285,7 +285,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m(
message<true, fail_body, headers> m(
std::piecewise_construct,
std::forward_as_tuple(fc, ios_));
m.method = "GET";
@@ -318,7 +318,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m(
message<true, fail_body, headers> m(
std::piecewise_construct,
std::forward_as_tuple(fc, ios_));
m.method = "GET";
@@ -353,7 +353,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m(
message<true, fail_body, headers> m(
std::piecewise_construct,
std::forward_as_tuple(fc, ios_));
m.method = "GET";
@@ -388,7 +388,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m(
message<true, fail_body, headers> m(
std::piecewise_construct,
std::forward_as_tuple(fc, ios_));
m.method = "GET";
@@ -418,7 +418,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
string_write_stream> fs(fc, ios_);
message_v1<true, fail_body, headers> m(
message<true, fail_body, headers> m(
std::piecewise_construct,
std::forward_as_tuple(fc, ios_));
m.method = "GET";
@@ -449,7 +449,7 @@ public:
{
// auto content-length HTTP/1.0
{
message_v1<true, string_body, headers> m;
message<true, string_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 10;
@@ -466,7 +466,7 @@ public:
}
// keep-alive HTTP/1.0
{
message_v1<true, string_body, headers> m;
message<true, string_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 10;
@@ -484,7 +484,7 @@ public:
}
// upgrade HTTP/1.0
{
message_v1<true, string_body, headers> m;
message<true, string_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 10;
@@ -502,7 +502,7 @@ public:
}
// no content-length HTTP/1.0
{
message_v1<true, unsized_body, headers> m;
message<true, unsized_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 10;
@@ -522,7 +522,7 @@ public:
}
// auto content-length HTTP/1.1
{
message_v1<true, string_body, headers> m;
message<true, string_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 11;
@@ -539,7 +539,7 @@ public:
}
// close HTTP/1.1
{
message_v1<true, string_body, headers> m;
message<true, string_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 11;
@@ -561,7 +561,7 @@ public:
}
// upgrade HTTP/1.1
{
message_v1<true, empty_body, headers> m;
message<true, empty_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 11;
@@ -576,7 +576,7 @@ public:
}
// no content-length HTTP/1.1
{
message_v1<true, unsized_body, headers> m;
message<true, unsized_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 11;
@@ -600,7 +600,7 @@ public:
void testConvert()
{
message_v1<true, string_body, headers> m;
message<true, string_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 11;
@@ -613,7 +613,7 @@ public:
void testOstream()
{
message_v1<true, string_body, headers> m;
message<true, string_body, headers> m;
m.method = "GET";
m.url = "/";
m.version = 11;
+1 -1
View File
@@ -184,7 +184,7 @@ public:
for(n = 0; n < limit; ++n)
{
// valid
http::request_v1<http::empty_body> req;
http::request<http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;