Add `BalsaHeaders::RemoveHeadersIf` to remove headers based on a predicate. This new method allows removing headers where the key and/or value satisfy a given function, providing more flexible header removal capabilities. PiperOrigin-RevId: 805081402
diff --git a/quiche/balsa/balsa_headers.cc b/quiche/balsa/balsa_headers.cc index 1747609..5f67152 100644 --- a/quiche/balsa/balsa_headers.cc +++ b/quiche/balsa/balsa_headers.cc
@@ -6,6 +6,7 @@ #include <sys/types.h> +#include <cstddef> #include <cstdint> #include <functional> #include <string> @@ -677,6 +678,25 @@ } } +void BalsaHeaders::RemoveHeadersIf( + std::function<bool(const absl::string_view, const absl::string_view)> + predicate) { + for (HeaderLines::size_type i = 0; i < header_lines_.size(); ++i) { + if (header_lines_[i].skip) { + continue; + } + + HeaderLineDescription& line = header_lines_[i]; + const absl::string_view key( + GetPtr(line.buffer_base_idx) + line.first_char_idx, + line.key_end_idx - line.first_char_idx); + const absl::string_view value = GetValueFromHeaderLineDescription(line); + if (predicate(key, value)) { + line.skip = true; + } + } +} + bool BalsaHeaders::HasHeadersWithPrefix(absl::string_view prefix) const { for (HeaderLines::size_type i = 0; i < header_lines_.size(); ++i) { if (header_lines_[i].skip) {
diff --git a/quiche/balsa/balsa_headers.h b/quiche/balsa/balsa_headers.h index 3f7aa6d..7b42e3e 100644 --- a/quiche/balsa/balsa_headers.h +++ b/quiche/balsa/balsa_headers.h
@@ -647,6 +647,11 @@ // Removes all headers starting with 'key' [case insensitive] void RemoveAllHeadersWithPrefix(absl::string_view prefix) override; + // Removes all headers that satisfy the predicate. + void RemoveHeadersIf( + std::function<bool(const absl::string_view, const absl::string_view)> + predicate); + // Returns true if we have at least one header with given prefix // [case insensitive]. Currently for test use only. bool HasHeadersWithPrefix(absl::string_view prefix) const override;
diff --git a/quiche/balsa/balsa_headers_test.cc b/quiche/balsa/balsa_headers_test.cc index d18759d..fff74aa 100644 --- a/quiche/balsa/balsa_headers_test.cc +++ b/quiche/balsa/balsa_headers_test.cc
@@ -18,6 +18,7 @@ #include <vector> #include "absl/base/macros.h" +#include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" @@ -3629,6 +3630,41 @@ EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_coalesced); } +TEST(BalsaHeaders, RemoveHeadersIf) { + BalsaHeaders headers; + headers.AppendHeader("keep", "val-keep"); + headers.AppendHeader("first-1", "val-first-1"); + headers.AppendHeader("first-2", "val-first-2"); + headers.AppendHeader("second", "val-second"); + EXPECT_EQ(headers.GetHeader("keep"), "val-keep"); + EXPECT_EQ(headers.GetHeader("first-1"), "val-first-1"); + EXPECT_EQ(headers.GetHeader("first-2"), "val-first-2"); + EXPECT_EQ(headers.GetHeader("second"), "val-second"); + + headers.RemoveHeadersIf( + [](const absl::string_view key, const absl::string_view /*value*/) { + return absl::StartsWith(key, "first"); + }); + EXPECT_FALSE(headers.HasHeader("first-1")); + EXPECT_FALSE(headers.HasHeader("first-2")); + EXPECT_EQ(headers.GetHeader("keep"), "val-keep"); + EXPECT_EQ(headers.GetHeader("first-1"), ""); + EXPECT_EQ(headers.GetHeader("first-2"), ""); + EXPECT_EQ(headers.GetHeader("second"), "val-second"); + + headers.RemoveHeadersIf( + [](const absl::string_view key, const absl::string_view /*value*/) { + return key == "second"; + }); + EXPECT_FALSE(headers.HasHeader("first-1")); + EXPECT_FALSE(headers.HasHeader("first-2")); + EXPECT_FALSE(headers.HasHeader("second")); + EXPECT_EQ(headers.GetHeader("keep"), "val-keep"); + EXPECT_EQ(headers.GetHeader("first-1"), ""); + EXPECT_EQ(headers.GetHeader("first-2"), ""); + EXPECT_EQ(headers.GetHeader("second"), ""); +} + TEST(BalsaHeadersTest, RemoveLastTokenFromOneLineHeader) { BalsaHeaders headers = CreateHTTPHeaders(true,