Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http: remove getAll() header map API and switch all usages to get() #13363

Merged
merged 12 commits into from
Oct 12, 2020
11 changes: 2 additions & 9 deletions include/envoy/http/header_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,14 +506,7 @@ class HeaderMap {
virtual uint64_t byteSize() const PURE;

/**
* Get a header by key.
* @param key supplies the header key.
* @return the header entry if it exists otherwise nullptr.
*/
virtual const HeaderEntry* get(const LowerCaseString& key) const PURE;

/**
* This is a wrapper for the return result from getAll(). It avoids a copy when translating from
* This is a wrapper for the return result from get(). It avoids a copy when translating from
* non-const HeaderEntry to const HeaderEntry and only provides const access to the result.
*/
using NonConstGetResult = absl::InlinedVector<HeaderEntry*, 1>;
Expand All @@ -536,7 +529,7 @@ class HeaderMap {
* @param key supplies the header key.
* @return all header entries matching the key.
*/
virtual GetResult getAll(const LowerCaseString& key) const PURE;
virtual GetResult get(const LowerCaseString& key) const PURE;

// aliases to make iterate() and iterateReverse() callbacks easier to read
enum class Iterate { Continue, Break };
Expand Down
10 changes: 6 additions & 4 deletions source/common/formatter/substitution_formatter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -863,13 +863,15 @@ HeaderFormatter::HeaderFormatter(const std::string& main_header,
: main_header_(main_header), alternative_header_(alternative_header), max_length_(max_length) {}

const Http::HeaderEntry* HeaderFormatter::findHeader(const Http::HeaderMap& headers) const {
const Http::HeaderEntry* header = headers.get(main_header_);
const auto header = headers.get(main_header_);

if (!header && !alternative_header_.get().empty()) {
return headers.get(alternative_header_);
if (header.empty() && !alternative_header_.get().empty()) {
const auto alternate_header = headers.get(alternative_header_);
// TODO(mattklein123): Potentially log all header values.
return alternate_header.empty() ? nullptr : alternate_header[0];
}

return header;
return header.empty() ? nullptr : header[0];
}

absl::optional<std::string> HeaderFormatter::format(const Http::HeaderMap& headers) const {
Expand Down
7 changes: 4 additions & 3 deletions source/common/grpc/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,14 @@ std::string Common::getGrpcMessage(const Http::ResponseHeaderOrTrailerMap& trail

absl::optional<google::rpc::Status>
Common::getGrpcStatusDetailsBin(const Http::HeaderMap& trailers) {
const Http::HeaderEntry* details_header = trailers.get(Http::Headers::get().GrpcStatusDetailsBin);
if (!details_header) {
const auto details_header = trailers.get(Http::Headers::get().GrpcStatusDetailsBin);
if (details_header.empty()) {
return absl::nullopt;
}

// Some implementations use non-padded base64 encoding for grpc-status-details-bin.
auto decoded_value = Base64::decodeWithoutPadding(details_header->value().getStringView());
// This is effectively a trusted header so using the first value is fine.
auto decoded_value = Base64::decodeWithoutPadding(details_header[0]->value().getStringView());
if (decoded_value.empty()) {
return absl::nullopt;
}
Expand Down
9 changes: 5 additions & 4 deletions source/common/http/hash_policy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ class HeaderHashMethod : public HashMethodImplBase {
const StreamInfo::FilterStateSharedPtr) const override {
absl::optional<uint64_t> hash;

const HeaderEntry* header = headers.get(header_name_);
if (header) {
// TODO(mattklein123): Potentially hash on all headers.
const auto header = headers.get(header_name_);
if (!header.empty()) {
if (regex_rewrite_ != nullptr) {
hash = HashUtil::xxHash64(regex_rewrite_->replaceAll(header->value().getStringView(),
hash = HashUtil::xxHash64(regex_rewrite_->replaceAll(header[0]->value().getStringView(),
regex_rewrite_substitution_));
} else {
hash = HashUtil::xxHash64(header->value().getStringView());
hash = HashUtil::xxHash64(header[0]->value().getStringView());
}
}
return hash;
Expand Down
7 changes: 1 addition & 6 deletions source/common/http/header_map_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -473,12 +473,7 @@ void HeaderMapImpl::verifyByteSizeInternalForTest() const {
ASSERT(cached_byte_size_ == byte_size);
}

const HeaderEntry* HeaderMapImpl::get(const LowerCaseString& key) const {
const auto result = getAll(key);
return result.empty() ? nullptr : result[0];
}

HeaderMap::GetResult HeaderMapImpl::getAll(const LowerCaseString& key) const {
HeaderMap::GetResult HeaderMapImpl::get(const LowerCaseString& key) const {
return HeaderMap::GetResult(const_cast<HeaderMapImpl*>(this)->getExisting(key));
}

Expand Down
8 changes: 2 additions & 6 deletions source/common/http/header_map_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ class HeaderMapImpl : NonCopyable {
void setReferenceKey(const LowerCaseString& key, absl::string_view value);
void setCopy(const LowerCaseString& key, absl::string_view value);
uint64_t byteSize() const;
const HeaderEntry* get(const LowerCaseString& key) const;
HeaderMap::GetResult getAll(const LowerCaseString& key) const;
HeaderMap::GetResult get(const LowerCaseString& key) const;
void iterate(HeaderMap::ConstIterateCb cb) const;
void iterateReverse(HeaderMap::ConstIterateCb cb) const;
void clear();
Expand Down Expand Up @@ -369,12 +368,9 @@ template <class Interface> class TypedHeaderMapImpl : public HeaderMapImpl, publ
HeaderMapImpl::setCopy(key, value);
}
uint64_t byteSize() const override { return HeaderMapImpl::byteSize(); }
const HeaderEntry* get(const LowerCaseString& key) const override {
HeaderMap::GetResult get(const LowerCaseString& key) const override {
return HeaderMapImpl::get(key);
}
HeaderMap::GetResult getAll(const LowerCaseString& key) const override {
return HeaderMapImpl::getAll(key);
}
void iterate(HeaderMap::ConstIterateCb cb) const override { HeaderMapImpl::iterate(cb); }
void iterateReverse(HeaderMap::ConstIterateCb cb) const override {
HeaderMapImpl::iterateReverse(cb);
Expand Down
13 changes: 5 additions & 8 deletions source/common/http/header_utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,10 @@ HeaderUtility::HeaderData::HeaderData(const envoy::config::route::v3::HeaderMatc

void HeaderUtility::getAllOfHeader(const HeaderMap& headers, absl::string_view key,
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
std::vector<absl::string_view>& out) {
headers.iterate([key = LowerCaseString(std::string(key)),
&out](const HeaderEntry& header) -> HeaderMap::Iterate {
if (header.key() == key.get().c_str()) {
out.emplace_back(header.value().getStringView());
}
return HeaderMap::Iterate::Continue;
});
const auto all_headers = headers.get(Http::LowerCaseString(std::string(key)));
for (size_t i = 0; i < all_headers.size(); i++) {
out.emplace_back(all_headers[i]->value().getStringView());
}
}

bool HeaderUtility::matchHeaders(const HeaderMap& request_headers,
Expand All @@ -108,7 +105,7 @@ bool HeaderUtility::matchHeaders(const HeaderMap& request_headers,
HeaderUtility::GetAllOfHeaderAsStringResult
HeaderUtility::getAllOfHeaderAsString(const HeaderMap& headers, const Http::LowerCaseString& key) {
GetAllOfHeaderAsStringResult result;
const auto header_value = headers.getAll(key);
const auto header_value = headers.get(key);

if (header_value.empty()) {
// Empty for clarity. Avoid handling the empty case in the block below if the runtime feature
Expand Down
9 changes: 6 additions & 3 deletions source/common/http/utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ bool Utility::sanitizeConnectionHeader(Http::RequestHeaderMap& headers) {
bool keep_header = false;

// Determine whether the nominated header contains invalid values
const HeaderEntry* nominated_header = nullptr;
HeaderMap::GetResult nominated_header;

if (lcs_header_to_remove == Http::Headers::get().Connection) {
// Remove the connection header from the nominated tokens if it's self nominated
Expand All @@ -672,8 +672,10 @@ bool Utility::sanitizeConnectionHeader(Http::RequestHeaderMap& headers) {
nominated_header = headers.get(lcs_header_to_remove);
}

if (nominated_header) {
auto nominated_header_value_sv = nominated_header->value().getStringView();
if (!nominated_header.empty()) {
// NOTE: The TE header is an inline header, so by definition if we operate on it there can
// only be a single value. In all other cases we remove the nominated header.
auto nominated_header_value_sv = nominated_header[0]->value().getStringView();

const bool is_te_header = (lcs_header_to_remove == Http::Headers::get().TE);

Expand All @@ -684,6 +686,7 @@ bool Utility::sanitizeConnectionHeader(Http::RequestHeaderMap& headers) {
}

if (is_te_header) {
ASSERT(nominated_header.size() == 1);
for (const auto& header_value :
StringUtil::splitToken(nominated_header_value_sv, ",", false)) {

Expand Down
14 changes: 8 additions & 6 deletions source/common/router/config_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -550,9 +550,10 @@ void RouteEntryImplBase::finalizeRequestHeaders(Http::RequestHeaderMap& headers,
if (!host_rewrite_.empty()) {
headers.setHost(host_rewrite_);
} else if (auto_host_rewrite_header_) {
const Http::HeaderEntry* header = headers.get(*auto_host_rewrite_header_);
if (header != nullptr) {
absl::string_view header_value = header->value().getStringView();
const auto header = headers.get(*auto_host_rewrite_header_);
if (!header.empty()) {
// This is a client controlled header, so only using the first value is fine.
const absl::string_view header_value = header[0]->value().getStringView();
if (!header_value.empty()) {
headers.setHost(header_value);
}
Expand Down Expand Up @@ -881,10 +882,11 @@ RouteConstSharedPtr RouteEntryImplBase::clusterEntry(const Http::HeaderMap& head
return shared_from_this();
} else {
ASSERT(!cluster_header_name_.get().empty());
const Http::HeaderEntry* entry = headers.get(cluster_header_name_);
const auto entry = headers.get(cluster_header_name_);
std::string final_cluster_name;
if (entry) {
final_cluster_name = std::string(entry->value().getStringView());
if (!entry.empty()) {
// This is a client controlled header, so only using the first value is fine.
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
final_cluster_name = std::string(entry[0]->value().getStringView());
}

// NOTE: Though we return a shared_ptr here, the current ownership model assumes that
Expand Down
6 changes: 4 additions & 2 deletions source/common/router/header_formatter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,10 @@ parseRequestHeader(absl::string_view param) {
Http::LowerCaseString header_name{std::string(param)};
return [header_name](const Envoy::StreamInfo::StreamInfo& stream_info) -> std::string {
if (const auto* request_headers = stream_info.getRequestHeaders()) {
if (const auto* entry = request_headers->get(header_name)) {
return std::string(entry->value().getStringView());
const auto entry = request_headers->get(header_name);
if (!entry.empty()) {
// TODO(mattklein123): Potentially use all header values.
return std::string(entry[0]->value().getStringView());
}
}
return std::string();
Expand Down
7 changes: 4 additions & 3 deletions source/common/router/reset_header_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ ResetHeaderParserImpl::ResetHeaderParserImpl(
absl::optional<std::chrono::milliseconds>
ResetHeaderParserImpl::parseInterval(TimeSource& time_source,
const Http::HeaderMap& headers) const {
const Http::HeaderEntry* header = headers.get(name_);
const auto header = headers.get(name_);

if (header == nullptr) {
if (header.empty()) {
return absl::nullopt;
}

const auto& header_value = header->value().getStringView();
// This is effectively a trusted header so only using the first value is fine.
const auto& header_value = header[0]->value().getStringView();
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
uint64_t num_seconds{};

switch (format_) {
Expand Down
7 changes: 4 additions & 3 deletions source/common/router/router_ratelimit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,17 @@ bool RequestHeadersAction::populateDescriptor(const Router::RouteEntry&,
const Http::HeaderMap& headers,
const Network::Address::Instance&,
const envoy::config::core::v3::Metadata*) const {
const Http::HeaderEntry* header_value = headers.get(header_name_);
const auto header_value = headers.get(header_name_);

// If header is not present in the request and if skip_if_absent is true skip this descriptor,
// while calling rate limiting service. If skip_if_absent is false, do not call rate limiting
// service.
if (!header_value) {
if (header_value.empty()) {
return skip_if_absent_;
}
// TODO(mattklein123): Potentially populate all header values.
descriptor.entries_.push_back(
{descriptor_key_, std::string(header_value->value().getStringView())});
{descriptor_key_, std::string(header_value[0]->value().getStringView())});
return true;
}

Expand Down
9 changes: 5 additions & 4 deletions source/common/router/scoped_config_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,16 @@ HeaderValueExtractorImpl::HeaderValueExtractorImpl(

std::unique_ptr<ScopeKeyFragmentBase>
HeaderValueExtractorImpl::computeFragment(const Http::HeaderMap& headers) const {
const Envoy::Http::HeaderEntry* header_entry =
const auto header_entry =
headers.get(Envoy::Http::LowerCaseString(header_value_extractor_config_.name()));
if (header_entry == nullptr) {
if (header_entry.empty()) {
return nullptr;
}

std::vector<absl::string_view> elements{header_entry->value().getStringView()};
// This is a client controlled header so using the first value is fine.
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
std::vector<absl::string_view> elements{header_entry[0]->value().getStringView()};
if (header_value_extractor_config_.element_separator().length() > 0) {
elements = absl::StrSplit(header_entry->value().getStringView(),
elements = absl::StrSplit(header_entry[0]->value().getStringView(),
header_value_extractor_config_.element_separator());
}
switch (header_value_extractor_config_.extract_type_case()) {
Expand Down
5 changes: 3 additions & 2 deletions source/common/tracing/http_tracer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,9 @@ absl::string_view RequestHeaderCustomTag::value(const CustomTagContext& ctx) con
if (!ctx.request_headers) {
return default_value_;
}
const Http::HeaderEntry* entry = ctx.request_headers->get(name_);
return entry ? entry->value().getStringView() : default_value_;
// TODO(mattklein123): Potentially populate all header values.
const auto entry = ctx.request_headers->get(name_);
return !entry.empty() ? entry[0]->value().getStringView() : default_value_;
}

MetadataCustomTag::MetadataCustomTag(const std::string& tag,
Expand Down
13 changes: 7 additions & 6 deletions source/common/upstream/original_dst_cluster.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,14 @@ Network::Address::InstanceConstSharedPtr
OriginalDstCluster::LoadBalancer::requestOverrideHost(LoadBalancerContext* context) {
Network::Address::InstanceConstSharedPtr request_host;
const Http::HeaderMap* downstream_headers = context->downstreamHeaders();
if (downstream_headers &&
downstream_headers->get(Http::Headers::get().EnvoyOriginalDstHost) != nullptr) {
const std::string request_override_host(
downstream_headers->get(Http::Headers::get().EnvoyOriginalDstHost)
->value()
.getStringView());
Http::HeaderMap::GetResult override_header;
if (downstream_headers) {
override_header = downstream_headers->get(Http::Headers::get().EnvoyOriginalDstHost);
}
if (!override_header.empty()) {
try {
// This is client controlled so using the first value is fine.
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
const std::string request_override_host(override_header[0]->value().getStringView());
request_host = Network::Utility::parseInternetAddressAndPort(request_override_host, false);
ENVOY_LOG(debug, "Using request override host {}.", request_override_host);
} catch (const Envoy::EnvoyException& e) {
Expand Down
21 changes: 12 additions & 9 deletions source/extensions/access_loggers/grpc/http_grpc_access_log_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,10 @@ void HttpGrpcAccessLog::emitLog(const Http::RequestHeaderMap& request_headers,
auto* logged_headers = request_properties->mutable_request_headers();

for (const auto& header : request_headers_to_log_) {
const Http::HeaderEntry* entry = request_headers.get(header);
if (entry != nullptr) {
logged_headers->insert({header.get(), std::string(entry->value().getStringView())});
const auto entry = request_headers.get(header);
if (!entry.empty()) {
// TODO(mattklein123): Potentially log all header values.
logged_headers->insert({header.get(), std::string(entry[0]->value().getStringView())});
}
}
}
Expand All @@ -136,9 +137,10 @@ void HttpGrpcAccessLog::emitLog(const Http::RequestHeaderMap& request_headers,
auto* logged_headers = response_properties->mutable_response_headers();

for (const auto& header : response_headers_to_log_) {
const Http::HeaderEntry* entry = response_headers.get(header);
if (entry != nullptr) {
logged_headers->insert({header.get(), std::string(entry->value().getStringView())});
const auto entry = response_headers.get(header);
if (!entry.empty()) {
// TODO(mattklein123): Potentially log all header values.
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
logged_headers->insert({header.get(), std::string(entry[0]->value().getStringView())});
}
}
}
Expand All @@ -147,9 +149,10 @@ void HttpGrpcAccessLog::emitLog(const Http::RequestHeaderMap& request_headers,
auto* logged_headers = response_properties->mutable_response_trailers();

for (const auto& header : response_trailers_to_log_) {
const Http::HeaderEntry* entry = response_trailers.get(header);
if (entry != nullptr) {
logged_headers->insert({header.get(), std::string(entry->value().getStringView())});
const auto entry = response_trailers.get(header);
if (!entry.empty()) {
// TODO(mattklein123): Potentially log all header values.
logged_headers->insert({header.get(), std::string(entry[0]->value().getStringView())});
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ ResponsePtr RawHttpClientImpl::toResponse(Http::ResponseMessagePtr message) {
// headers_to_remove in a variable first.
std::vector<Http::LowerCaseString> headers_to_remove;
if (status_code == enumToInt(Http::Code::OK)) {
const auto& get_result = message->headers().getAll(storage_header_name);
const auto& get_result = message->headers().get(storage_header_name);
for (size_t i = 0; i < get_result.size(); ++i) {
const Http::HeaderEntry* entry = get_result[i];
if (entry != nullptr) {
Expand Down
Loading