From 72dc439584ef3cdf7a75dfae5cf085c259acd654 Mon Sep 17 00:00:00 2001 From: dvtate Date: Fri, 10 Oct 2025 15:44:48 -0500 Subject: [PATCH] Add basic_fields::contains member function --- include/boost/beast/http/fields.hpp | 14 +++++++++++ include/boost/beast/http/impl/fields.hpp | 24 ++++++++++++++++--- include/boost/beast/websocket/impl/accept.hpp | 4 ++-- test/beast/http/fields.cpp | 14 +++++++++++ 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/include/boost/beast/http/fields.hpp b/include/boost/beast/http/fields.hpp index d799d3ab..8dd92a44 100644 --- a/include/boost/beast/http/fields.hpp +++ b/include/boost/beast/http/fields.hpp @@ -647,6 +647,20 @@ public: // //-------------------------------------------------------------------------- + /** Returns `true` if there is a field with the specified name. + + @param name The field name. + */ + bool + contains(field name) const; + + /** Returns `true` if there is a field with the specified name. + + @param name The field name. It is interpreted as a case-insensitive string. + */ + bool + contains(string_view name) const; + /** Return the number of fields with the specified name. @param name The field name. diff --git a/include/boost/beast/http/impl/fields.hpp b/include/boost/beast/http/impl/fields.hpp index bd3e74a9..b42a3ccd 100644 --- a/include/boost/beast/http/impl/fields.hpp +++ b/include/boost/beast/http/impl/fields.hpp @@ -659,6 +659,24 @@ swap( // //------------------------------------------------------------------------------ +template +inline +bool +basic_fields:: +contains(field name) const +{ + BOOST_ASSERT(name != field::unknown); + return contains(to_string(name)); +} + +template +bool +basic_fields:: +contains(string_view name) const +{ + return find(name) != end(); +} + template inline std::size_t @@ -835,7 +853,7 @@ bool basic_fields:: has_content_length_impl() const { - return count(field::content_length) > 0; + return contains(field::content_length); } template @@ -999,7 +1017,7 @@ insert_element(element& e) set_.upper_bound(e.name_string(), key_compare{}); if(before == set_.begin()) { - BOOST_ASSERT(count(e.name_string()) == 0); + BOOST_ASSERT(! contains(e.name_string())); set_.insert_before(before, e); list_.push_back(e); return; @@ -1008,7 +1026,7 @@ insert_element(element& e) // VFALCO is it worth comparing `field name` first? if(! beast::iequals(e.name_string(), last->name_string())) { - BOOST_ASSERT(count(e.name_string()) == 0); + BOOST_ASSERT(! contains(e.name_string())); set_.insert_before(before, e); list_.push_back(e); return; diff --git a/include/boost/beast/websocket/impl/accept.hpp b/include/boost/beast/websocket/impl/accept.hpp index 0fab245d..e20b4d1c 100644 --- a/include/boost/beast/websocket/impl/accept.hpp +++ b/include/boost/beast/websocket/impl/accept.hpp @@ -77,7 +77,7 @@ build_response( { decorator_opt(res); decorator(res); - if(! res.count(http::field::server)) + if(! res.contains(http::field::server)) res.set(http::field::server, string_view(BOOST_BEAST_VERSION_STRING)); }; @@ -97,7 +97,7 @@ build_response( return err(error::bad_http_version); if(req.method() != http::verb::get) return err(error::bad_method); - if(! req.count(http::field::host)) + if(! req.contains(http::field::host)) return err(error::no_host); { auto const it = req.find(http::field::connection); diff --git a/test/beast/http/fields.cpp b/test/beast/http/fields.cpp index 71a0fb39..c93a493a 100644 --- a/test/beast/http/fields.cpp +++ b/test/beast/http/fields.cpp @@ -476,6 +476,20 @@ public: BEAST_THROWS(f.set(big_name, ""), boost::system::system_error); BEAST_THROWS(f.set("", big_value), boost::system::system_error); } + + { + fields f; + BEAST_EXPECT(! f.contains("Content-Type")); + f.set("Content-Type", "text/html"); + BEAST_EXPECT(f.contains("Content-Type")); + BEAST_EXPECT(f.contains("content-type")); + BEAST_EXPECT(! f.contains(field::user_agent)); + + f.insert("AA", "a"); + f.insert("AA", "b"); + f.insert("AA", "c"); + BEAST_EXPECT(f.contains("AA")); + } } struct sized_body