Improved beast::http::message:

* Add headers::erase
* Set http::message version with std::pair
* Use std::pair for headers::value_type
This commit is contained in:
Vinnie Falco
2014-10-30 17:16:54 -07:00
parent 825b18cf71
commit d073425b44
3 changed files with 96 additions and 42 deletions

View File

@@ -38,11 +38,7 @@ namespace http {
class headers class headers
{ {
public: public:
struct value_type using value_type = std::pair<std::string, std::string>;
{
std::string field;
std::string value;
};
private: private:
struct element struct element
@@ -139,6 +135,13 @@ public:
void void
clear() noexcept; clear() noexcept;
/** Remove a field.
@return The number of fields removed.
*/
template <class = void>
std::size_t
erase (std::string const& field);
/** Append a field value. /** Append a field value.
If a field value already exists the new value will be If a field value already exists the new value will be
extended as per RFC2616 Section 4.2. extended as per RFC2616 Section 4.2.
@@ -164,8 +167,8 @@ template <class>
headers::element::element ( headers::element::element (
std::string const& f, std::string const& v) std::string const& f, std::string const& v)
{ {
data.field = f; data.first = f;
data.value = v; data.second = v;
} }
template <class String> template <class String>
@@ -173,7 +176,7 @@ bool
headers::less::operator() ( headers::less::operator() (
String const& lhs, element const& rhs) const String const& lhs, element const& rhs) const
{ {
return beast::ci_less::operator() (lhs, rhs.data.field); return beast::ci_less::operator() (lhs, rhs.data.first);
} }
template <class String> template <class String>
@@ -181,7 +184,7 @@ bool
headers::less::operator() ( headers::less::operator() (
element const& lhs, String const& rhs) const element const& lhs, String const& rhs) const
{ {
return beast::ci_less::operator() (lhs.data.field, rhs); return beast::ci_less::operator() (lhs.data.first, rhs);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -210,7 +213,7 @@ inline
headers::headers (headers const& other) headers::headers (headers const& other)
{ {
for (auto const& e : other.list_) for (auto const& e : other.list_)
append (e.data.field, e.data.value); append (e.data.first, e.data.second);
} }
inline inline
@@ -219,7 +222,7 @@ headers::operator= (headers const& other)
{ {
clear(); clear();
for (auto const& e : other.list_) for (auto const& e : other.list_)
append (e.data.field, e.data.value); append (e.data.first, e.data.second);
return *this; return *this;
} }
@@ -269,7 +272,7 @@ headers::operator[] (std::string const& field) const
auto const found (find (field)); auto const found (find (field));
if (found == end()) if (found == end())
return none; return none;
return found->value; return found->second;
} }
template <class> template <class>
@@ -280,6 +283,20 @@ headers::clear() noexcept
delete &(*iter++); delete &(*iter++);
} }
template <class>
std::size_t
headers::erase (std::string const& field)
{
auto const iter = set_.find(field, less{});
if (iter == set_.end())
return 0;
element& e = *iter;
set_.erase(set_.iterator_to(e));
list_.erase(list_.iterator_to(e));
delete &e;
return 1;
}
template <class> template <class>
void void
headers::append (std::string const& field, headers::append (std::string const& field,
@@ -296,7 +313,7 @@ headers::append (std::string const& field,
} }
// If field already exists, append comma // If field already exists, append comma
// separated value as per RFC2616 section 4.2 // separated value as per RFC2616 section 4.2
auto& cur (result.first->data.value); auto& cur (result.first->data.second);
cur.reserve (cur.size() + 1 + value.size()); cur.reserve (cur.size() + 1 + value.size());
cur.append (1, ','); cur.append (1, ',');
cur.append (value); cur.append (value);
@@ -304,6 +321,36 @@ headers::append (std::string const& field,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class Streambuf>
void
write (Streambuf& stream, std::string const& s)
{
stream.commit (boost::asio::buffer_copy (
stream.prepare (s.size()), boost::asio::buffer(s)));
}
template <class Streambuf>
void
write (Streambuf& stream, char const* s)
{
auto const len (::strlen(s));
stream.commit (boost::asio::buffer_copy (
stream.prepare (len), boost::asio::buffer (s, len)));
}
template <class Streambuf>
void
write (Streambuf& stream, headers const& h)
{
for (auto const& _ : h)
{
write (stream, _.first);
write (stream, ": ");
write (stream, _.second);
write (stream, "\r\n");
}
}
template <class> template <class>
std::string std::string
to_string (headers const& h) to_string (headers const& h)
@@ -311,13 +358,13 @@ to_string (headers const& h)
std::string s; std::string s;
std::size_t n (0); std::size_t n (0);
for (auto const& e : h) for (auto const& e : h)
n += e.field.size() + 2 + e.value.size() + 2; n += e.first.size() + 2 + e.second.size() + 2;
s.reserve (n); s.reserve (n);
for (auto const& e : h) for (auto const& e : h)
{ {
s.append (e.field); s.append (e.first);
s.append (": "); s.append (": ");
s.append (e.value); s.append (e.second);
s.append ("\r\n"); s.append ("\r\n");
} }
return s; return s;
@@ -338,10 +385,10 @@ build_map (headers const& h)
std::map <std::string, std::string> c; std::map <std::string, std::string> c;
for (auto const& e : h) for (auto const& e : h)
{ {
auto key (e.field); auto key (e.first);
// TODO Replace with safe C++14 version // TODO Replace with safe C++14 version
std::transform (key.begin(), key.end(), key.begin(), ::tolower); std::transform (key.begin(), key.end(), key.begin(), ::tolower);
c [key] = e.value; c [key] = e.second;
} }
return c; return c;
} }

View File

@@ -35,6 +35,20 @@
namespace beast { namespace beast {
namespace http { namespace http {
inline
std::pair<int, int>
http_1_0()
{
return std::pair<int, int>(1, 0);
}
inline
std::pair<int, int>
http_1_1()
{
return std::pair<int, int>(1, 1);
}
class message class message
{ {
private: private:
@@ -178,6 +192,12 @@ public:
version_ = std::make_pair (major, minor); version_ = std::make_pair (major, minor);
} }
void
version (std::pair<int, int> p)
{
version_ = p;
}
std::pair<int, int> std::pair<int, int>
version() const version() const
{ {
@@ -233,23 +253,6 @@ message::operator= (message&& other)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class Streambuf>
void
write (Streambuf& stream, std::string const& s)
{
stream.commit (boost::asio::buffer_copy (
stream.prepare (s.size()), boost::asio::buffer(s)));
}
template <class Streambuf>
void
write (Streambuf& stream, char const* s)
{
auto const len (::strlen(s));
stream.commit (boost::asio::buffer_copy (
stream.prepare (len), boost::asio::buffer (s, len)));
}
template <class Streambuf> template <class Streambuf>
void void
write (Streambuf& stream, message const& m) write (Streambuf& stream, message const& m)
@@ -276,13 +279,7 @@ write (Streambuf& stream, message const& m)
write (stream, m.reason()); write (stream, m.reason());
} }
write (stream, "\r\n"); write (stream, "\r\n");
for (auto const& header : m.headers) write(stream, m.headers);
{
write (stream, header.field);
write (stream, ": ");
write (stream, header.value);
write (stream, "\r\n");
}
write (stream, "\r\n"); write (stream, "\r\n");
} }

View File

@@ -58,9 +58,19 @@ public:
log << "|" << result.first.headers["Field"] << "|"; log << "|" << result.first.headers["Field"] << "|";
} }
void
test_headers()
{
headers h;
h.append("Field", "Value");
expect (h.erase("Field") == 1);
}
void void
run() run()
{ {
test_headers();
{ {
std::string const text = std::string const text =
"GET / HTTP/1.1\r\n" "GET / HTTP/1.1\r\n"