http_proxy.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
20 
22 
23 #include <string.h>
24 
25 #include <memory>
26 #include <string>
27 #include <vector>
28 
29 #include "absl/container/inlined_vector.h"
30 #include "absl/status/status.h"
31 #include "absl/status/statusor.h"
32 #include "absl/strings/match.h"
33 #include "absl/strings/str_cat.h"
34 #include "absl/strings/str_split.h"
35 #include "absl/strings/string_view.h"
36 #include "absl/strings/strip.h"
37 
38 #include <grpc/support/alloc.h>
39 #include <grpc/support/log.h>
41 
44 #include "src/core/lib/gpr/env.h"
49 #include "src/core/lib/slice/b64.h"
52 
53 namespace grpc_core {
54 namespace {
55 
62 // TODO(hork): change this to return std::string
63 char* GetHttpProxyServer(const grpc_channel_args* args, char** user_cred) {
64  GPR_ASSERT(user_cred != nullptr);
66  char* proxy_name = nullptr;
67  char** authority_strs = nullptr;
68  size_t authority_nstrs;
69  /* We check the following places to determine the HTTP proxy to use, stopping
70  * at the first one that is set:
71  * 1. GRPC_ARG_HTTP_PROXY channel arg
72  * 2. grpc_proxy environment variable
73  * 3. https_proxy environment variable
74  * 4. http_proxy environment variable
75  * If none of the above are set, then no HTTP proxy will be used.
76  */
77  auto uri_str = UniquePtr<char>(
79  if (uri_str == nullptr) uri_str = UniquePtr<char>(gpr_getenv("grpc_proxy"));
80  if (uri_str == nullptr) uri_str = UniquePtr<char>(gpr_getenv("https_proxy"));
81  if (uri_str == nullptr) uri_str = UniquePtr<char>(gpr_getenv("http_proxy"));
82  if (uri_str == nullptr) return nullptr;
83  // an emtpy value means "don't use proxy"
84  if (uri_str.get()[0] == '\0') return nullptr;
85  uri = URI::Parse(uri_str.get());
86  if (!uri.ok() || uri->authority().empty()) {
87  gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var. Error: %s",
88  uri.status().ToString().c_str());
89  return nullptr;
90  }
91  if (uri->scheme() != "http") {
92  gpr_log(GPR_ERROR, "'%s' scheme not supported in proxy URI",
93  uri->scheme().c_str());
94  return nullptr;
95  }
96  /* Split on '@' to separate user credentials from host */
97  gpr_string_split(uri->authority().c_str(), "@", &authority_strs,
98  &authority_nstrs);
99  GPR_ASSERT(authority_nstrs != 0); /* should have at least 1 string */
100  if (authority_nstrs == 1) {
101  /* User cred not present in authority */
102  proxy_name = authority_strs[0];
103  } else if (authority_nstrs == 2) {
104  /* User cred found */
105  *user_cred = authority_strs[0];
106  proxy_name = authority_strs[1];
107  gpr_log(GPR_DEBUG, "userinfo found in proxy URI");
108  } else {
109  /* Bad authority */
110  for (size_t i = 0; i < authority_nstrs; i++) {
111  gpr_free(authority_strs[i]);
112  }
113  proxy_name = nullptr;
114  }
115  gpr_free(authority_strs);
116  return proxy_name;
117 }
118 
119 // Adds the default port if target does not contain a port.
120 std::string MaybeAddDefaultPort(absl::string_view target) {
121  absl::string_view host;
123  SplitHostPort(target, &host, &port);
124  if (port.empty()) {
125  return JoinHostPort(host, kDefaultSecurePortInt);
126  }
127  return std::string(target);
128 }
129 
130 } // namespace
131 
133  const grpc_channel_args* args,
134  char** name_to_resolve,
135  grpc_channel_args** new_args) {
137  return false;
138  }
139  char* user_cred = nullptr;
140  *name_to_resolve = GetHttpProxyServer(args, &user_cred);
141  if (*name_to_resolve == nullptr) return false;
142  std::string server_target;
144  auto no_use_proxy = [&]() {
145  gpr_free(*name_to_resolve);
146  *name_to_resolve = nullptr;
147  gpr_free(user_cred);
148  return false;
149  };
150  if (!uri.ok() || uri->path().empty()) {
152  "'http_proxy' environment variable set, but cannot "
153  "parse server URI '%s' -- not using proxy. Error: %s",
154  server_uri, uri.status().ToString().c_str());
155  return no_use_proxy();
156  }
157  if (uri->scheme() == "unix") {
158  gpr_log(GPR_INFO, "not using proxy for Unix domain socket '%s'",
159  server_uri);
160  return no_use_proxy();
161  }
162  /* Prefer using 'no_grpc_proxy'. Fallback on 'no_proxy' if it is not set. */
163  auto no_proxy_str = UniquePtr<char>(gpr_getenv("no_grpc_proxy"));
164  if (no_proxy_str == nullptr) {
165  no_proxy_str = UniquePtr<char>(gpr_getenv("no_proxy"));
166  }
167  if (no_proxy_str != nullptr) {
168  bool use_proxy = true;
171  if (!SplitHostPort(absl::StripPrefix(uri->path(), "/"), &server_host,
172  &server_port)) {
174  "unable to split host and port, not checking no_proxy list for "
175  "host '%s'",
176  server_uri);
177  } else {
178  std::vector<absl::string_view> no_proxy_hosts =
179  absl::StrSplit(no_proxy_str.get(), ',', absl::SkipEmpty());
180  for (const auto& no_proxy_entry : no_proxy_hosts) {
181  if (absl::EndsWithIgnoreCase(server_host, no_proxy_entry)) {
182  gpr_log(GPR_INFO, "not using proxy for host in no_proxy list '%s'",
183  server_uri);
184  use_proxy = false;
185  break;
186  }
187  }
188  if (!use_proxy) return no_use_proxy();
189  }
190  }
191  server_target =
192  MaybeAddDefaultPort(absl::StripPrefix(uri->path(), "/")).c_str();
195  const_cast<char*>(GRPC_ARG_HTTP_CONNECT_SERVER),
196  const_cast<char*>(server_target.c_str())));
198  if (user_cred != nullptr) {
199  /* Use base64 encoding for user credentials as stated in RFC 7617 */
200  auto encoded_user_cred =
201  UniquePtr<char>(grpc_base64_encode(user_cred, strlen(user_cred), 0, 0));
202  header =
203  absl::StrCat("Proxy-Authorization:Basic ", encoded_user_cred.get());
205  const_cast<char*>(GRPC_ARG_HTTP_CONNECT_HEADERS),
206  const_cast<char*>(header.c_str())));
207  }
208  *new_args = grpc_channel_args_copy_and_add(args, args_to_add.data(),
209  args_to_add.size());
210  gpr_free(user_cred);
211  return true;
212 }
213 
216  true /* at_start */,
217  std::unique_ptr<ProxyMapperInterface>(new HttpProxyMapper()));
218 }
219 
220 } // namespace grpc_core
absl::StrSplit
strings_internal::Splitter< typename strings_internal::SelectDelimiter< Delimiter >::type, AllowEmpty, absl::string_view > StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d)
Definition: abseil-cpp/absl/strings/str_split.h:499
grpc_channel_args_find_string
char * grpc_channel_args_find_string(const grpc_channel_args *args, const char *name)
Definition: channel_args.cc:441
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
grpc_core::HttpProxyMapper::MapName
bool MapName(const char *server_uri, const grpc_channel_args *args, char **name_to_resolve, grpc_channel_args **new_args) override
Definition: http_proxy.cc:132
log.h
gpr_string_split
void gpr_string_split(const char *input, const char *sep, char ***strs, size_t *nstrs)
Definition: string.cc:300
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
http_proxy.h
grpc_core
Definition: call_metric_recorder.h:31
string.h
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
server_port
static int server_port
Definition: bad_server_response_test.cc:86
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
resolve_address.h
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
grpc_core::SplitHostPort
bool SplitHostPort(absl::string_view name, absl::string_view *host, absl::string_view *port)
Definition: host_port.cc:88
GRPC_ARG_HTTP_CONNECT_HEADERS
#define GRPC_ARG_HTTP_CONNECT_HEADERS
Definition: http_connect_handshaker.h:33
env.h
grpc_channel_arg_string_create
grpc_arg grpc_channel_arg_string_create(char *name, char *value)
Definition: channel_args.cc:476
absl::StripPrefix
ABSL_MUST_USE_RESULT absl::string_view StripPrefix(absl::string_view str, absl::string_view prefix)
Definition: abseil-cpp/absl/strings/strip.h:73
run_xds_tests.server_uri
string server_uri
Definition: run_xds_tests.py:3320
grpc_core::URI::Parse
static absl::StatusOr< URI > Parse(absl::string_view uri_text)
Definition: uri_parser.cc:209
grpc_channel_args_find_bool
bool grpc_channel_args_find_bool(const grpc_channel_args *args, const char *name, bool default_value)
Definition: channel_args.cc:465
grpc_channel_args
Definition: grpc_types.h:132
memory.h
string_util.h
absl::SkipEmpty
Definition: abseil-cpp/absl/strings/str_split.h:347
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
gpr_getenv
char * gpr_getenv(const char *name)
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
grpc_core::URI::authority
const std::string & authority() const
Definition: uri_parser.h:69
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
GRPC_ARG_HTTP_PROXY
#define GRPC_ARG_HTTP_PROXY
Definition: grpc_types.h:418
grpc_core::JoinHostPort
std::string JoinHostPort(absl::string_view host, int port)
Definition: host_port.cc:32
absl::InlinedVector::push_back
void push_back(const_reference v)
Definition: abseil-cpp/absl/container/inlined_vector.h:682
header
struct absl::base_internal::@2940::AllocList::Header header
b64.h
absl::InlinedVector::data
pointer data() noexcept
Definition: abseil-cpp/absl/container/inlined_vector.h:302
host_port.h
absl::InlinedVector::size
size_type size() const noexcept
Definition: abseil-cpp/absl/container/inlined_vector.h:270
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
grpc_core::UniquePtr
std::unique_ptr< T, DefaultDeleteChar > UniquePtr
Definition: src/core/lib/gprpp/memory.h:43
grpc_base64_encode
char * grpc_base64_encode(const void *vdata, size_t data_size, int url_safe, int multiline)
Definition: b64.cc:59
tests.unit._exit_scenarios.port
port
Definition: _exit_scenarios.py:179
grpc_core::HttpProxyMapper
Definition: http_proxy.h:31
grpc_core::URI::scheme
const std::string & scheme() const
Definition: uri_parser.h:68
absl::StatusOr::ok
ABSL_MUST_USE_RESULT bool ok() const
Definition: abseil-cpp/absl/status/statusor.h:491
absl::EndsWithIgnoreCase
bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) noexcept
Definition: abseil-cpp/absl/strings/match.cc:36
http2_server_health_check.server_host
server_host
Definition: http2_server_health_check.py:27
grpc_core::ProxyMapperRegistry::Register
static void Register(bool at_start, std::unique_ptr< ProxyMapperInterface > mapper)
Definition: proxy_mapper_registry.cc:53
alloc.h
http_connect_handshaker.h
grpc_core::kDefaultSecurePortInt
constexpr int kDefaultSecurePortInt
Definition: resolve_address.h:39
channel_args.h
gpr_strdup
GPRAPI char * gpr_strdup(const char *src)
Definition: string.cc:39
GPR_DEBUG
#define GPR_DEBUG
Definition: include/grpc/impl/codegen/log.h:55
absl::StatusOr
Definition: abseil-cpp/absl/status/statusor.h:187
uri_parser.h
absl::InlinedVector
Definition: abseil-cpp/absl/container/inlined_vector.h:69
proxy_mapper_registry.h
grpc_core::RegisterHttpProxyMapper
void RegisterHttpProxyMapper()
Definition: http_proxy.cc:214
GRPC_ARG_ENABLE_HTTP_PROXY
#define GRPC_ARG_ENABLE_HTTP_PROXY
Definition: grpc_types.h:415
setup.target
target
Definition: third_party/bloaty/third_party/protobuf/python/setup.py:179
grpc_channel_args_copy_and_add
grpc_channel_args * grpc_channel_args_copy_and_add(const grpc_channel_args *src, const grpc_arg *to_add, size_t num_to_add)
Definition: channel_args.cc:224
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
absl::StatusOr::status
const Status & status() const &
Definition: abseil-cpp/absl/status/statusor.h:678
GRPC_ARG_HTTP_CONNECT_SERVER
#define GRPC_ARG_HTTP_CONNECT_SERVER
Definition: http_connect_handshaker.h:28
port_platform.h


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:02