• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/core/client_channel/lb_metadata.h"
16 
17 #include "absl/log/log.h"
18 
19 namespace grpc_core {
20 
21 //
22 // LbMetadata
23 //
24 
25 namespace {
26 
27 class Encoder {
28  public:
Encode(const Slice & key,const Slice & value)29   void Encode(const Slice& key, const Slice& value) {
30     out_.emplace_back(std::string(key.as_string_view()),
31                       std::string(value.as_string_view()));
32   }
33 
34   template <class Which>
Encode(Which,const typename Which::ValueType & value)35   void Encode(Which, const typename Which::ValueType& value) {
36     auto value_slice = Which::Encode(value);
37     out_.emplace_back(std::string(Which::key()),
38                       std::string(value_slice.as_string_view()));
39   }
40 
Encode(GrpcTimeoutMetadata,const typename GrpcTimeoutMetadata::ValueType &)41   void Encode(GrpcTimeoutMetadata,
42               const typename GrpcTimeoutMetadata::ValueType&) {}
Encode(HttpPathMetadata,const Slice &)43   void Encode(HttpPathMetadata, const Slice&) {}
Encode(HttpMethodMetadata,const typename HttpMethodMetadata::ValueType &)44   void Encode(HttpMethodMetadata,
45               const typename HttpMethodMetadata::ValueType&) {}
46 
Take()47   std::vector<std::pair<std::string, std::string>> Take() {
48     return std::move(out_);
49   }
50 
51  private:
52   std::vector<std::pair<std::string, std::string>> out_;
53 };
54 
55 }  // namespace
56 
Lookup(absl::string_view key,std::string * buffer) const57 absl::optional<absl::string_view> LbMetadata::Lookup(
58     absl::string_view key, std::string* buffer) const {
59   if (batch_ == nullptr) return absl::nullopt;
60   return batch_->GetStringValue(key, buffer);
61 }
62 
63 std::vector<std::pair<std::string, std::string>>
TestOnlyCopyToVector() const64 LbMetadata::TestOnlyCopyToVector() const {
65   if (batch_ == nullptr) return {};
66   Encoder encoder;
67   batch_->Encode(&encoder);
68   return encoder.Take();
69 }
70 
71 //
72 // MetadataMutationHandler
73 //
74 
Apply(LoadBalancingPolicy::MetadataMutations & metadata_mutations,grpc_metadata_batch * metadata)75 void MetadataMutationHandler::Apply(
76     LoadBalancingPolicy::MetadataMutations& metadata_mutations,
77     grpc_metadata_batch* metadata) {
78   for (auto& p : metadata_mutations.metadata_) {
79     absl::string_view key = p.first;
80     Slice& value =
81         grpc_event_engine::experimental::internal::SliceCast<Slice>(p.second);
82     // TODO(roth): Should we prevent this from setting special keys like
83     // :authority, :path, content-type, etc?
84     metadata->Remove(key);
85     // Gross, egregious hack to support legacy grpclb behavior.
86     // TODO(ctiller): Use a promise context for this once that plumbing is done.
87     if (key == GrpcLbClientStatsMetadata::key()) {
88       metadata->Set(
89           GrpcLbClientStatsMetadata(),
90           const_cast<GrpcLbClientStats*>(
91               reinterpret_cast<const GrpcLbClientStats*>(value.data())));
92       continue;
93     }
94     metadata->Append(key, std::move(value),
95                      [key](absl::string_view error, const Slice& value) {
96                        LOG(ERROR) << error << " key:" << key
97                                   << " value:" << value.as_string_view();
98                      });
99   }
100 }
101 
102 //
103 // MaybeOverrideAuthority()
104 //
105 
MaybeOverrideAuthority(grpc_event_engine::experimental::Slice authority_override,grpc_metadata_batch * metadata)106 void MaybeOverrideAuthority(
107     grpc_event_engine::experimental::Slice authority_override,
108     grpc_metadata_batch* metadata) {
109   // Skip if no override requested.
110   if (authority_override.empty()) return;
111   // Skip if authority already set by the application on this RPC.
112   if (metadata->get_pointer(HttpAuthorityMetadata()) != nullptr) return;
113   // Otherwise, apply override.
114   Slice& authority =
115       grpc_event_engine::experimental::internal::SliceCast<Slice>(
116           authority_override);
117   metadata->Set(HttpAuthorityMetadata(), std::move(authority));
118 }
119 
120 }  // namespace grpc_core
121