Derive header from Fields (API Change)

This commit is contained in:
Vinnie Falco committed 2017-07-20 08:12:18 -07:00
1 parent 5f2e7560b6
commit 2af19481a9
35 files changed
+304 -298

No files matched your search

+8 -48
View File
@@ -268,54 +268,14 @@ public:
boost::lexical_cast<std::string>(value));
}
#if BEAST_DOXYGEN
private:
#endif
string_view
method_impl() const
{
return (*this)[":method"];
}
void
method_impl(string_view s)
{
if(s.empty())
this->erase(":method");
else
this->replace(":method", s);
}
string_view
target_impl() const
{
return (*this)[":target"];
}
void
target_impl(string_view s)
{
if(s.empty())
this->erase(":target");
else
return this->replace(":target", s);
}
string_view
reason_impl() const
{
return (*this)[":reason"];
}
void
reason_impl(string_view s)
{
if(s.empty())
this->erase(":reason");
else
this->replace(":reason", s);
}
protected:
// for header
string_view method_impl() const;
string_view target_impl() const;
string_view reason_impl() const;
void method_impl(string_view s);
void target_impl(string_view s);
void reason_impl(string_view s);
private:
struct element
+65
View File
@@ -26,6 +26,71 @@ basic_fields<Allocator>::
//------------------------------------------------------------------------------
template<class Allocator>
inline
string_view
basic_fields<Allocator>::
method_impl() const
{
return (*this)[":method"];
}
template<class Allocator>
inline
string_view
basic_fields<Allocator>::
target_impl() const
{
return (*this)[":target"];
}
template<class Allocator>
inline
string_view
basic_fields<Allocator>::
reason_impl() const
{
return (*this)[":reason"];
}
template<class Allocator>
inline
void
basic_fields<Allocator>::
method_impl(string_view s)
{
if(s.empty())
this->erase(":method");
else
this->replace(":method", s);
}
template<class Allocator>
inline
void
basic_fields<Allocator>::
target_impl(string_view s)
{
if(s.empty())
this->erase(":target");
else
return this->replace(":target", s);
}
template<class Allocator>
inline
void
basic_fields<Allocator>::
reason_impl(string_view s)
{
if(s.empty())
this->erase(":reason");
else
this->replace(":reason", s);
}
//------------------------------------------------------------------------------
template<class Allocator>
class basic_fields<Allocator>::
const_iterator
+33 -29
View File
@@ -30,7 +30,7 @@ get_method_string() const
{
if(method_ != verb::unknown)
return to_string(method_);
return fields.method_impl();
return this->method_impl();
}
template<class Fields>
@@ -43,7 +43,7 @@ set_method(verb v)
BOOST_THROW_EXCEPTION(
std::invalid_argument{"unknown verb"});
method_ = v;
fields.method_impl({});
this->method_impl({});
}
template<class Fields>
@@ -54,9 +54,9 @@ set_method(string_view s)
{
method_ = string_to_verb(s);
if(method_ != verb::unknown)
fields.method_impl({});
this->method_impl({});
else
fields.method_impl(s);
this->method_impl(s);
}
template<class Fields>
@@ -65,7 +65,7 @@ string_view
header<false, Fields>::
get_reason() const
{
auto const s = fields.reason_impl();
auto const s = this->reason_impl();
if(! s.empty())
return s;
return obsolete_reason(result_);
@@ -74,25 +74,29 @@ get_reason() const
template<class Fields>
void
swap(
header<true, Fields>& m1,
header<true, Fields>& m2)
header<true, Fields>& h1,
header<true, Fields>& h2)
{
using std::swap;
swap(m1.version, m2.version);
swap(m1.fields, m2.fields);
swap(m1.method_, m2.method_);
swap(
static_cast<Fields&>(h1),
static_cast<Fields&>(h2));
swap(h1.version, h2.version);
swap(h1.method_, h2.method_);
}
template<class Fields>
void
swap(
header<false, Fields>& a,
header<false, Fields>& b)
header<false, Fields>& h1,
header<false, Fields>& h2)
{
using std::swap;
swap(a.version, b.version);
swap(a.fields, b.fields);
swap(a.result_, b.result_);
swap(
static_cast<Fields&>(h1),
static_cast<Fields&>(h2));
swap(h1.version, h2.version);
swap(h1.result_, h2.result_);
}
template<bool isRequest, class Body, class Fields>
@@ -113,11 +117,11 @@ is_keep_alive(header<isRequest, Fields> const& msg)
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
if(msg.version == 11)
{
if(token_list{msg.fields["Connection"]}.exists("close"))
if(token_list{msg["Connection"]}.exists("close"))
return false;
return true;
}
if(token_list{msg.fields["Connection"]}.exists("keep-alive"))
if(token_list{msg["Connection"]}.exists("keep-alive"))
return true;
return false;
}
@@ -129,7 +133,7 @@ is_upgrade(header<isRequest, Fields> const& msg)
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
if(msg.version == 10)
return false;
if(token_list{msg.fields["Connection"]}.exists("upgrade"))
if(token_list{msg["Connection"]}.exists("upgrade"))
return true;
return false;
}
@@ -219,15 +223,15 @@ prepare(message<isRequest, Body, Fields>& msg,
detail::prepare_options(pi, msg,
std::forward<Options>(options)...);
if(msg.fields.exists("Connection"))
if(msg.exists("Connection"))
BOOST_THROW_EXCEPTION(std::invalid_argument{
"prepare called with Connection field set"});
if(msg.fields.exists("Content-Length"))
if(msg.exists("Content-Length"))
BOOST_THROW_EXCEPTION(std::invalid_argument{
"prepare called with Content-Length field set"});
if(token_list{msg.fields["Transfer-Encoding"]}.exists("chunked"))
if(token_list{msg["Transfer-Encoding"]}.exists("chunked"))
BOOST_THROW_EXCEPTION(std::invalid_argument{
"prepare called with Transfer-Encoding: chunked set"});
@@ -245,7 +249,7 @@ prepare(message<isRequest, Body, Fields>& msg,
if(*pi.content_length > 0 ||
msg.method() == verb::post)
{
msg.fields.insert(
msg.insert(
"Content-Length", *pi.content_length);
}
}
@@ -258,7 +262,7 @@ prepare(message<isRequest, Body, Fields>& msg,
msg.result() != status::no_content &&
msg.result() != status::not_modified)
{
msg.fields.insert(
msg.insert(
"Content-Length", *pi.content_length);
}
}
@@ -267,39 +271,39 @@ prepare(message<isRequest, Body, Fields>& msg,
}
else if(msg.version >= 11)
{
msg.fields.insert("Transfer-Encoding", "chunked");
msg.insert("Transfer-Encoding", "chunked");
}
}
auto const content_length =
msg.fields.exists("Content-Length");
msg.exists("Content-Length");
if(pi.connection_value)
{
switch(*pi.connection_value)
{
case connection::upgrade:
msg.fields.insert("Connection", "upgrade");
msg.insert("Connection", "upgrade");
break;
case connection::keep_alive:
if(msg.version < 11)
{
if(content_length)
msg.fields.insert("Connection", "keep-alive");
msg.insert("Connection", "keep-alive");
}
break;
case connection::close:
if(msg.version >= 11)
msg.fields.insert("Connection", "close");
msg.insert("Connection", "close");
break;
}
}
// rfc7230 6.7.
if(msg.version < 11 && token_list{
msg.fields["Connection"]}.exists("upgrade"))
msg["Connection"]}.exists("upgrade"))
BOOST_THROW_EXCEPTION(std::invalid_argument{
"invalid version for Connection: upgrade"});
}
+4 -4
View File
@@ -94,12 +94,12 @@ get(error_code& ec, Visit&& visit)
case do_construct:
{
chunked_ = token_list{
m_.fields["Transfer-Encoding"]}.exists("chunked");
close_ = token_list{m_.fields["Connection"]}.exists("close") ||
(m_.version < 11 && ! m_.fields.exists("Content-Length"));
m_["Transfer-Encoding"]}.exists("chunked");
close_ = token_list{m_["Connection"]}.exists("close") ||
(m_.version < 11 && ! m_.exists("Content-Length"));
auto os = ostream(b_);
detail::write_start_line(os, m_);
detail::write_fields(os, m_.fields);
detail::write_fields(os, m_);
os << "\r\n";
if(chunked_)
goto go_init_c;
+1 -1
View File
@@ -828,7 +828,7 @@ operator<<(std::ostream& os,
header<isRequest, Fields> const& msg)
{
detail::write_start_line(os, msg);
detail::write_fields(os, msg.fields);
detail::write_fields(os, msg);
os << "\r\n";
return os;
}
+18 -24
View File
@@ -45,7 +45,7 @@ template<bool isRequest, class Fields = fields>
struct header;
template<class Fields>
struct header<true, Fields>
struct header<true, Fields> : Fields
#endif
{
/// Indicates if the header is a request or response.
@@ -59,6 +59,17 @@ struct header<true, Fields>
/// The type representing the fields.
using fields_type = Fields;
/** The HTTP-version.
This holds both the major and minor version numbers,
using these formulas:
@code
int major = version / 10;
int minor = version % 10;
@endcode
*/
int version;
/// Default constructor
header() = default;
@@ -96,25 +107,11 @@ struct header<true, Fields>
header>::value>::type>
explicit
header(Arg1&& arg1, ArgN&&... argn)
: fields(std::forward<Arg1>(arg1),
: Fields(std::forward<Arg1>(arg1),
std::forward<ArgN>(argn)...)
{
}
/** The HTTP-version.
This holds both the major and minor version numbers,
using these formulas:
@code
int major = version / 10;
int minor = version % 10;
@endcode
*/
int version;
/// The HTTP field values.
fields_type fields;
/** Return the request-method verb.
If the request-method is not one of the recognized verbs,
@@ -181,7 +178,7 @@ struct header<true, Fields>
string_view
target() const
{
return fields.target_impl();
return this->target_impl();
}
/** Set the request-target string.
@@ -193,7 +190,7 @@ struct header<true, Fields>
void
target(string_view s)
{
fields.target_impl(s);
this->target_impl(s);
}
private:
@@ -230,7 +227,7 @@ private:
@li Invoke algorithms which operate on the header only.
*/
template<class Fields>
struct header<false, Fields>
struct header<false, Fields> : Fields
{
/// Indicates if the header is a request or response.
static bool constexpr is_request = false;
@@ -249,9 +246,6 @@ struct header<false, Fields>
*/
int version;
/// The HTTP field values.
fields_type fields;
/// Default constructor.
header() = default;
@@ -283,7 +277,7 @@ struct header<false, Fields>
header>::value>::type>
explicit
header(Arg1&& arg1, ArgN&&... argn)
: fields(std::forward<Arg1>(arg1),
: Fields(std::forward<Arg1>(arg1),
std::forward<ArgN>(argn)...)
{
}
@@ -379,7 +373,7 @@ struct header<false, Fields>
void
reason(string_view s)
{
fields.reason_impl(s);
this->reason_impl(s);
}
private:
+1 -1
View File
@@ -208,7 +208,7 @@ private:
string_view value,
error_code&)
{
m_.fields.insert(name, value);
m_.insert(name, value);
}
void
+1 -2
View File
@@ -153,8 +153,7 @@ operator()(error_code ec, bool again)
ec = error::handshake_failed;
if(! ec)
{
pmd_read(
d.ws.pmd_config_, d.res.fields);
pmd_read(d.ws.pmd_config_, d.res);
d.ws.open(detail::role_type::server);
}
break;
+1 -2
View File
@@ -132,8 +132,7 @@ operator()(error_code ec, bool again)
// VFALCO Do we need the ability to move
// a message on the async_write?
//
pmd_read(
d.ws.pmd_config_, d.req.fields);
pmd_read(d.ws.pmd_config_, d.req);
http::async_write(d.ws.stream_,
d.req, std::move(*this));
// TODO We don't need d.req now. Figure
+2 -2
View File
@@ -23,9 +23,9 @@ is_upgrade(http::header<true, Fields> const& req)
return false;
if(! http::is_upgrade(req))
return false;
if(! http::token_list{req.fields["Upgrade"]}.exists("websocket"))
if(! http::token_list{req["Upgrade"]}.exists("websocket"))
return false;
if(! req.fields.exists("Sec-WebSocket-Version"))
if(! req.exists("Sec-WebSocket-Version"))
return false;
return true;
}
+27 -29
View File
@@ -117,7 +117,7 @@ do_accept(http::header<true, Fields> const& req,
// teardown if Connection: close.
return;
}
pmd_read(pmd_config_, req.fields);
pmd_read(pmd_config_, req);
open(detail::role_type::server);
}
@@ -137,7 +137,7 @@ do_handshake(response_type* res_p,
{
auto const req = build_request(
key, host, target, decorator);
pmd_read(pmd_config_, req.fields);
pmd_read(pmd_config_, req);
http::write(stream_, req, ec);
}
if(ec)
@@ -163,12 +163,12 @@ build_request(detail::sec_ws_key_type& key,
req.target(target);
req.version = 11;
req.method(http::verb::get);
req.fields.insert("Host", host);
req.fields.insert("Upgrade", "websocket");
req.fields.insert("Connection", "upgrade");
req.insert("Host", host);
req.insert("Upgrade", "websocket");
req.insert("Connection", "upgrade");
detail::make_sec_ws_key(key, maskgen_);
req.fields.insert("Sec-WebSocket-Key", key);
req.fields.insert("Sec-WebSocket-Version", "13");
req.insert("Sec-WebSocket-Key", key);
req.insert("Sec-WebSocket-Version", "13");
if(pmd_opts_.client_enable)
{
detail::pmd_offer config;
@@ -181,14 +181,13 @@ build_request(detail::sec_ws_key_type& key,
pmd_opts_.server_no_context_takeover;
config.client_no_context_takeover =
pmd_opts_.client_no_context_takeover;
detail::pmd_write(
req.fields, config);
detail::pmd_write(req, config);
}
decorator(req);
if(! req.fields.exists("User-Agent"))
if(! req.exists("User-Agent"))
{
static_string<20> s(BEAST_VERSION_STRING);
req.fields.insert("User-Agent", s);
req.insert("User-Agent", s);
}
return req;
}
@@ -204,10 +203,10 @@ build_response(http::header<true, Fields> const& req,
[&decorator](response_type& res)
{
decorator(res);
if(! res.fields.exists("Server"))
if(! res.exists("Server"))
{
static_string<20> s(BEAST_VERSION_STRING);
res.fields.insert("Server", s);
res.insert("Server", s);
}
};
auto err =
@@ -227,18 +226,18 @@ build_response(http::header<true, Fields> const& req,
return err("Wrong method");
if(! is_upgrade(req))
return err("Expected Upgrade request");
if(! req.fields.exists("Host"))
if(! req.exists("Host"))
return err("Missing Host");
if(! req.fields.exists("Sec-WebSocket-Key"))
if(! req.exists("Sec-WebSocket-Key"))
return err("Missing Sec-WebSocket-Key");
if(! http::token_list{req.fields["Upgrade"]}.exists("websocket"))
if(! http::token_list{req["Upgrade"]}.exists("websocket"))
return err("Missing websocket Upgrade token");
auto const key = req.fields["Sec-WebSocket-Key"];
auto const key = req["Sec-WebSocket-Key"];
if(key.size() > detail::sec_ws_key_type::max_size_n)
return err("Invalid Sec-WebSocket-Key");
{
auto const version =
req.fields["Sec-WebSocket-Version"];
req["Sec-WebSocket-Version"];
if(version.empty())
return err("Missing Sec-WebSocket-Version");
if(version != "13")
@@ -246,7 +245,7 @@ build_response(http::header<true, Fields> const& req,
response_type res;
res.result(http::status::upgrade_required);
res.version = req.version;
res.fields.insert("Sec-WebSocket-Version", "13");
res.insert("Sec-WebSocket-Version", "13");
prepare(res);
decorate(res);
return res;
@@ -257,18 +256,17 @@ build_response(http::header<true, Fields> const& req,
{
detail::pmd_offer offer;
detail::pmd_offer unused;
pmd_read(offer, req.fields);
pmd_negotiate(
res.fields, unused, offer, pmd_opts_);
pmd_read(offer, req);
pmd_negotiate(res, unused, offer, pmd_opts_);
}
res.result(http::status::switching_protocols);
res.version = req.version;
res.fields.insert("Upgrade", "websocket");
res.fields.insert("Connection", "upgrade");
res.insert("Upgrade", "websocket");
res.insert("Connection", "upgrade");
{
detail::sec_ws_accept_type accept;
detail::make_sec_ws_accept(accept, key);
res.fields.insert("Sec-WebSocket-Accept", accept);
res.insert("Sec-WebSocket-Accept", accept);
}
decorate(res);
return res;
@@ -288,14 +286,14 @@ do_response(http::header<false> const& res,
return false;
if(! is_upgrade(res))
return false;
if(! http::token_list{res.fields["Upgrade"]}.exists("websocket"))
if(! http::token_list{res["Upgrade"]}.exists("websocket"))
return false;
if(! res.fields.exists("Sec-WebSocket-Accept"))
if(! res.exists("Sec-WebSocket-Accept"))
return false;
detail::sec_ws_accept_type accept;
detail::make_sec_ws_accept(accept, key);
if(accept.compare(
res.fields["Sec-WebSocket-Accept"]) != 0)
res["Sec-WebSocket-Accept"]) != 0)
return false;
return true;
}();
@@ -305,7 +303,7 @@ do_response(http::header<false> const& res,
return;
}
detail::pmd_offer offer;
pmd_read(offer, res.fields);
pmd_read(offer, res);
// VFALCO see if offer satisfies pmd_config_,
// return an error if not.
pmd_config_ = offer; // overwrite for now
+4 -4
View File
@@ -1563,7 +1563,7 @@ public:
ws.handshake("localhost", "/",
[](request_type& req)
{
req.fields.insert("User-Agent", "Beast");
req.insert("User-Agent", "Beast");
});
}
catch(...)
@@ -1625,7 +1625,7 @@ public:
ws.handshake(res, "localhost", "/",
[](request_type& req)
{
req.fields.insert("User-Agent", "Beast");
req.insert("User-Agent", "Beast");
});
}
catch(...)
@@ -1771,7 +1771,7 @@ public:
ws.handshake("localhost", "/",
[](request_type& req)
{
req.fields.insert("User-Agent", "Beast");
req.insert("User-Agent", "Beast");
},
ec);
if(ec)
@@ -1833,7 +1833,7 @@ public:
ws.handshake(res, "localhost", "/",
[](request_type& req)
{
req.fields.insert("User-Agent", "Beast");
req.insert("User-Agent", "Beast");
},
ec);
if(ec)