From d073425b44d7cda1678002cbae814634a2676fe4 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Thu, 30 Oct 2014 17:16:54 -0700 Subject: [PATCH] Improved beast::http::message: * Add headers::erase * Set http::message version with std::pair * Use std::pair for headers::value_type --- src/beast/beast/http/headers.h | 83 +++++++++++++++++----- src/beast/beast/http/message.h | 45 ++++++------ src/beast/beast/http/tests/parser.test.cpp | 10 +++ 3 files changed, 96 insertions(+), 42 deletions(-) diff --git a/src/beast/beast/http/headers.h b/src/beast/beast/http/headers.h index 1deaaec0ee..ba06fcfbe6 100644 --- a/src/beast/beast/http/headers.h +++ b/src/beast/beast/http/headers.h @@ -38,11 +38,7 @@ namespace http { class headers { public: - struct value_type - { - std::string field; - std::string value; - }; + using value_type = std::pair; private: struct element @@ -139,6 +135,13 @@ public: void clear() noexcept; + /** Remove a field. + @return The number of fields removed. + */ + template + std::size_t + erase (std::string const& field); + /** Append a field value. If a field value already exists the new value will be extended as per RFC2616 Section 4.2. @@ -164,8 +167,8 @@ template headers::element::element ( std::string const& f, std::string const& v) { - data.field = f; - data.value = v; + data.first = f; + data.second = v; } template @@ -173,7 +176,7 @@ bool headers::less::operator() ( 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 @@ -181,7 +184,7 @@ bool headers::less::operator() ( 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) { for (auto const& e : other.list_) - append (e.data.field, e.data.value); + append (e.data.first, e.data.second); } inline @@ -219,7 +222,7 @@ headers::operator= (headers const& other) { clear(); for (auto const& e : other.list_) - append (e.data.field, e.data.value); + append (e.data.first, e.data.second); return *this; } @@ -269,7 +272,7 @@ headers::operator[] (std::string const& field) const auto const found (find (field)); if (found == end()) return none; - return found->value; + return found->second; } template @@ -280,6 +283,20 @@ headers::clear() noexcept delete &(*iter++); } +template +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 void headers::append (std::string const& field, @@ -296,7 +313,7 @@ headers::append (std::string const& field, } // If field already exists, append comma // 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.append (1, ','); cur.append (value); @@ -304,6 +321,36 @@ headers::append (std::string const& field, //------------------------------------------------------------------------------ +template +void +write (Streambuf& stream, std::string const& s) +{ + stream.commit (boost::asio::buffer_copy ( + stream.prepare (s.size()), boost::asio::buffer(s))); +} + +template +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 +void +write (Streambuf& stream, headers const& h) +{ + for (auto const& _ : h) + { + write (stream, _.first); + write (stream, ": "); + write (stream, _.second); + write (stream, "\r\n"); + } +} + template std::string to_string (headers const& h) @@ -311,13 +358,13 @@ to_string (headers const& h) std::string s; std::size_t n (0); 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); for (auto const& e : h) { - s.append (e.field); + s.append (e.first); s.append (": "); - s.append (e.value); + s.append (e.second); s.append ("\r\n"); } return s; @@ -338,10 +385,10 @@ build_map (headers const& h) std::map c; for (auto const& e : h) { - auto key (e.field); + auto key (e.first); // TODO Replace with safe C++14 version std::transform (key.begin(), key.end(), key.begin(), ::tolower); - c [key] = e.value; + c [key] = e.second; } return c; } diff --git a/src/beast/beast/http/message.h b/src/beast/beast/http/message.h index 66f3987849..1cc21254fd 100644 --- a/src/beast/beast/http/message.h +++ b/src/beast/beast/http/message.h @@ -35,6 +35,20 @@ namespace beast { namespace http { +inline +std::pair +http_1_0() +{ + return std::pair(1, 0); +} + +inline +std::pair +http_1_1() +{ + return std::pair(1, 1); +} + class message { private: @@ -178,6 +192,12 @@ public: version_ = std::make_pair (major, minor); } + void + version (std::pair p) + { + version_ = p; + } + std::pair version() const { @@ -233,23 +253,6 @@ message::operator= (message&& other) //------------------------------------------------------------------------------ -template -void -write (Streambuf& stream, std::string const& s) -{ - stream.commit (boost::asio::buffer_copy ( - stream.prepare (s.size()), boost::asio::buffer(s))); -} - -template -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 void write (Streambuf& stream, message const& m) @@ -276,13 +279,7 @@ write (Streambuf& stream, message const& m) write (stream, m.reason()); } write (stream, "\r\n"); - for (auto const& header : m.headers) - { - write (stream, header.field); - write (stream, ": "); - write (stream, header.value); - write (stream, "\r\n"); - } + write(stream, m.headers); write (stream, "\r\n"); } diff --git a/src/beast/beast/http/tests/parser.test.cpp b/src/beast/beast/http/tests/parser.test.cpp index c8e8ace4f6..6049d59d5a 100644 --- a/src/beast/beast/http/tests/parser.test.cpp +++ b/src/beast/beast/http/tests/parser.test.cpp @@ -58,9 +58,19 @@ public: log << "|" << result.first.headers["Field"] << "|"; } + void + test_headers() + { + headers h; + h.append("Field", "Value"); + expect (h.erase("Field") == 1); + } + void run() { + test_headers(); + { std::string const text = "GET / HTTP/1.1\r\n"