Refine FieldsReader concept (API Change)

* FieldsReader now requires chunked() and keep_alive()

* serializer logic calls into the reader to calculate
  the message metadata

* Removed some of the previous requirements of FieldsReader

Actions Required:

* Implement chunked() and keep_alive() for user defined FieldsReader types.
This commit is contained in:
Vinnie Falco
2017-07-20 08:15:27 -07:00
parent 087844c487
commit f9f6e1e0cc
13 changed files with 167 additions and 138 deletions
-9
View File
@@ -555,15 +555,6 @@ public:
}
protected:
/// Returns `true` if the value for Connection has "close" in the list.
bool has_close_impl() const;
/// Returns `true` if "chunked" is the last Transfer-Encoding
bool has_chunked_impl() const;
/// Returns `true` if the Content-Length field is present
bool has_content_length_impl() const;
/** Set or clear the method string.
@note Only called for requests.
+59 -43
View File
@@ -132,6 +132,12 @@ public:
}
};
bool
get_chunked() const;
bool
get_keep_alive(int version) const;
template<class String>
void
prepare(String& s, basic_fields const& f,
@@ -146,6 +152,8 @@ public:
static_string<max_static_start_line> ss_;
string_view sv_;
std::string s_;
bool chunked_;
bool keep_alive_;
public:
using const_buffers_type =
@@ -160,6 +168,18 @@ public:
reader(basic_fields const& f,
unsigned version, unsigned code);
bool
chunked()
{
return chunked_;
}
bool
keep_alive()
{
return keep_alive_;
}
const_buffers_type
get() const
{
@@ -170,6 +190,41 @@ public:
}
};
template<class Allocator>
bool
basic_fields<Allocator>::reader::
get_chunked() const
{
auto const te = token_list{
f_[field::transfer_encoding]};
for(auto it = te.begin(); it != te.end();)
{
auto next = std::next(it);
if(next == te.end())
return iequals(*it, "chunked");
it = next;
}
return false;
}
template<class Allocator>
bool
basic_fields<Allocator>::reader::
get_keep_alive(int version) const
{
if(version < 11)
{
auto const it = f_.find(field::connection);
if(it == f_.end())
return false;
return token_list{it->value()}.exists("keep-alive");
}
auto const it = f_.find(field::connection);
if(it == f_.end())
return true;
return ! token_list{it->value()}.exists("close");
}
template<class Allocator>
template<class String>
void
@@ -258,6 +313,8 @@ basic_fields<Allocator>::reader::
reader(basic_fields const& f,
unsigned version, verb v)
: f_(f)
, chunked_(get_chunked())
, keep_alive_(get_keep_alive(version))
{
try
{
@@ -276,6 +333,8 @@ basic_fields<Allocator>::reader::
reader(basic_fields const& f,
unsigned version, unsigned code)
: f_(f)
, chunked_(get_chunked())
, keep_alive_(get_keep_alive(version))
{
try
{
@@ -753,49 +812,6 @@ equal_range(string_view name) const ->
// Fields
template<class Allocator>
bool
basic_fields<Allocator>::
has_close_impl() const
{
auto const fit = set_.find(
to_string(field::connection), key_compare{});
if(fit == set_.end())
return false;
return token_list{fit->value()}.exists("close");
}
template<class Allocator>
bool
basic_fields<Allocator>::
has_chunked_impl() const
{
auto const fit = set_.find(to_string(
field::transfer_encoding), key_compare{});
if(fit == set_.end())
return false;
token_list const v{fit->value()};
auto it = v.begin();
if(it == v.end())
return false;
for(;;)
{
auto cur = it++;
if(it == v.end())
return iequals(*cur, "chunked");
}
}
template<class Allocator>
bool
basic_fields<Allocator>::
has_content_length_impl() const
{
auto const fit = set_.find(
to_string(field::content_length), key_compare{});
return fit != set_.end();
}
template<class Allocator>
inline
void
-27
View File
@@ -249,33 +249,6 @@ message(std::piecewise_construct_t,
{
}
template<bool isRequest, class Body, class Fields>
inline
bool
message<isRequest, Body, Fields>::
has_close() const
{
return this->has_close_impl();
}
template<bool isRequest, class Body, class Fields>
inline
bool
message<isRequest, Body, Fields>::
has_chunked() const
{
return this->has_chunked_impl();
}
template<bool isRequest, class Body, class Fields>
inline
bool
message<isRequest, Body, Fields>::
has_content_length() const
{
return this->has_content_length_impl();
}
template<bool isRequest, class Body, class Fields>
boost::optional<std::uint64_t>
message<isRequest, Body, Fields>::
+2 -4
View File
@@ -59,10 +59,8 @@ get(error_code& ec, Visit&& visit)
{
frdinit(std::integral_constant<bool,
isRequest>{});
close_ = m_.has_close() || (
m_.version < 11 &&
! m_.has_content_length());
if(m_.has_chunked())
close_ = ! frd_->keep_alive();
if(frd_->chunked())
goto go_init_c;
s_ = do_init;
BOOST_FALLTHROUGH;
-18
View File
@@ -483,24 +483,6 @@ struct message : header<isRequest, Fields>
return *this;
}
/// Returns `true` if "close" is specified in the Connection field.
bool
has_close() const;
/// Returns `true` if "chunked" is the last Transfer-Encoding.
bool
has_chunked() const;
/** Returns `true` if the Content-Length field is present.
This function checks the fields to determine if the content
length field is present, regardless of the actual value.
@note The contents of the body payload are not inspected.
*/
bool
has_content_length() const;
/** Returns the payload size of the body in octets if possible.
This function invokes the @b Body algorithm to measure