Skip to content

impl(rest): improve http header representation#16058

Open
scotthart wants to merge 10 commits intogoogleapis:mainfrom
scotthart:rab_prototype
Open

impl(rest): improve http header representation#16058
scotthart wants to merge 10 commits intogoogleapis:mainfrom
scotthart:rab_prototype

Conversation

@scotthart
Copy link
Copy Markdown
Member

Using plain std::string to represent HTTP headers, particularly the header names, requires all code locations to deal with the mismatch between std::string being case-sensitive and HTTP header names being case-insensitive. This PR extends the use of the HttpHeader type and introduces the HttpHeaderName type to consolidate such code. Additionally, it updates the definition of a collection of HttpHeader objects in HttpHeaders.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the HttpHeaderName class to handle case-insensitive HTTP header names by storing them in lowercase and refactors HttpHeader, RestContext, and RestRequest to use this new type along with absl::flat_hash_map for header storage. Feedback identifies opportunities to improve efficiency by removing redundant lowercase conversions in HttpHeader comparison and key-checking methods, and suggests using explicit HttpHeader construction in tests to improve clarity.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 27, 2026

Codecov Report

❌ Patch coverage is 97.50000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.69%. Comparing base (5b7b3c8) to head (86d7bf2).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ts/service_account_credentials_integration_test.cc 0.00% 2 Missing ⚠️
...oud/bigquery/v2/minimal/internal/rest_stub_utils.h 0.00% 1 Missing ⚠️
google/cloud/internal/rest_request.cc 90.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #16058   +/-   ##
=======================================
  Coverage   92.69%   92.69%           
=======================================
  Files        2343     2343           
  Lines      216541   216598   +57     
=======================================
+ Hits       200729   200783   +54     
- Misses      15812    15815    +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

// 32-bit architecture

GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
} // namespace rest_internal
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing nesting levels within pre-processor conditionals is generally considered bad practice.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

std::vector<std::string> values_;
};

// Abseil does not guarantee compatibility with 32-bit targets.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what that is supposed to mean. Consider something more descriptive.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Additionally, despite modest efforts on my part, I could not get the m32-pr build to compile using flat_hash_map with a custom key type using the 32-bit version of abseil provided by fedora. Perhaps with additional work this could be made to work, but it's currently not a priority.

Comment on lines +162 to +163
#if defined(_WIN64) || defined(__LP64__) || defined(__x86_64__) || \
defined(__ppc64__)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than trying to enumerate 64-bit targets, you might consider something like #if UINTPTR_MAX == UINT64_MAX (i.e., is a pointer 64 bits).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I was trying to find a better conditional for this.

Comment on lines +19 to +20
#if defined(_WIN64) || defined(__LP64__) || defined(__x86_64__) || \
defined(__ppc64__)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the same conditional here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// not test with. Support for such platforms is a community effort. Using
// std::unordered_map on 32-bit platforms reduces the likelihood of issues
// arising due to this arrangement.
#if UINTPTR_MAX == UINT64_MAX
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#incude <cstdint>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

} // namespace cloud
} // namespace google

#if UINTPTR_MAX != UINT64_MAX
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgive my memory failings, but how does absl::flat_hash_map know how to hash a HttpHeaderName?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HttpHeaderName type has an implicit std::string conversion operator.

#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_HTTP_HEADER_H

#include "google/cloud/version.h"
#if UINTPTR_MAX == UINT64_MAX
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better include <cstdint> before you use it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops; fixed.

HttpHeaderName(char const* name) // NOLINT(google-explicit-constructor)
: HttpHeaderName(std::string{name}) {}

operator std::string() const { // NOLINT(google-explicit-constructor)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does NOLINT(google-explicit-constructor) do anything on a non-constructor?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. There is not a different NOLINT for implicit conversion operators.

@scotthart scotthart enabled auto-merge (squash) March 31, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants