cli: Add HTTPResponseHeaders class for parsing response headers
What changed, and why it matters
This commit adds a small helper class for reading HTTP response headers in the bitcoin-cli command-line tool. It is purely new infrastructure code with no obvious security bug. There is no fix for a reported vulnerability and no indication this change itself introduces a vulnerability.
No security action required. Review the class for correctness as part of normal code review for the upcoming HTTPClient refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces HTTPResponseHeaders in src/bitcoin-cli.cpp, which wraps a LineReader to parse HTTP field lines into key/value pairs and provides a case-insensitive FindFirst lookup. It validates that each header line contains a colon and that the key is non-empty, throwing HTTPError otherwise. The code is intended for a future libevent-free HTTPClient implementation and references PR #35182 for a shared version.
Changed components
src/bitcoin-cli.cppInspect captured patch +61 / −0
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 3455aea7..55604d04 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -25,6 +25,7 @@
#include <util/chaintype.h>
#include <util/exception.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <util/time.h>
#include <util/translation.h>
@@ -36,6 +37,7 @@
#include <memory>
#include <optional>
#include <string>
+#include <string_view>
#include <tuple>
#ifndef WIN32
@@ -75,6 +77,65 @@ static const std::string DEFAULT_NBLOCKS = "1";
/** Default -color setting. */
static const std::string DEFAULT_COLOR_SETTING{"auto"};
+struct HTTPError : std::runtime_error {
+ explicit inline HTTPError(const std::string& msg) : std::runtime_error(msg) {}
+};
+
+/** Parses the headers of an HTTP response.
+ *
+ * May be replaced by the corresponding methods in HTTPHeaders from
+ * https://github.com/bitcoin/bitcoin/pull/35182 once that class is in a
+ * shared location.
+ */
+class HTTPResponseHeaders
+{
+ std::vector<std::pair<std::string, std::string>> m_headers;
+
+public:
+ void Read(util::LineReader& reader);
+ std::optional<std::string> FindFirst(std::string_view key) const;
+};
+
+// Named Read() in HTTPHeaders (see PR #35182).
+void HTTPResponseHeaders::Read(util::LineReader& reader)
+{
+ // Headers https://httpwg.org/specs/rfc9110.html#rfc.section.6.3
+ // A sequence of Field Lines https://httpwg.org/specs/rfc9110.html#rfc.section.5.2
+ while (auto maybe_line = reader.ReadLine()) {
+ const std::string& line = *maybe_line;
+
+ // An empty line indicates end of the headers section https://www.rfc-editor.org/rfc/rfc2616#section-4
+ if (line.empty()) return;
+
+ // Header line must have at least one ":"
+ // keys are not allowed to have delimiters like ":" but values are
+ // https://httpwg.org/specs/rfc9110.html#rfc.section.5.6.2
+ const size_t pos{line.find(':')};
+ if (pos == std::string::npos) throw HTTPError{"Header missing colon (:)"};
+
+ // Whitespace is optional
+ std::string key = util::TrimString(std::string_view(line).substr(0, pos));
+ std::string value = util::TrimString(std::string_view(line).substr(pos + 1));
+
+ // Header keys are Field Names: https://httpwg.org/specs/rfc9110.html#fields.names
+ // which consist of "tokens": https://httpwg.org/specs/rfc9110.html#rfc.section.5.6.2
+ // that can not be empty.
+ if (key.empty()) throw HTTPError{"Empty header name"};
+
+ m_headers.emplace_back(std::move(key), std::move(value));
+ }
+}
+
+std::optional<std::string> HTTPResponseHeaders::FindFirst(std::string_view key) const
+{
+ for (const auto& item : m_headers) {
+ if (CaseInsensitiveEqual(key, item.first)) {
+ return item.second;
+ }
+ }
+ return std::nullopt;
+}
+
static void SetupCliArgs(ArgsManager& argsman)
{
SetupHelpOptions(argsman);
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.