Merge pull request #9653 from grpc/revert-9606-port-9488

Revert "Port #9488 and part of #9463"
diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c
index 4ab4673..06038bb 100644
--- a/src/core/ext/client_channel/client_channel.c
+++ b/src/core/ext/client_channel/client_channel.c
@@ -44,8 +44,8 @@
 #include <grpc/support/useful.h>
 
 #include "src/core/ext/client_channel/http_connect_handshaker.h"
-#include "src/core/ext/client_channel/http_proxy.h"
 #include "src/core/ext/client_channel/lb_policy_registry.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/ext/client_channel/subchannel.h"
 #include "src/core/lib/channel/channel_args.h"
@@ -153,10 +153,6 @@
  */
 
 typedef struct client_channel_channel_data {
-  /** server name */
-  char *server_name;
-  /** HTTP CONNECT proxy to use, if any */
-  char *proxy_name;
   /** resolver for this channel */
   grpc_resolver *resolver;
   /** have we started resolving this channel */
@@ -317,17 +313,6 @@
     // Use pick_first if nothing was specified and we didn't select grpclb
     // above.
     if (lb_policy_name == NULL) lb_policy_name = "pick_first";
-    // If using a proxy, add channel arg for server in HTTP CONNECT request.
-    if (chand->proxy_name != NULL) {
-      grpc_arg new_arg;
-      new_arg.key = GRPC_ARG_HTTP_CONNECT_SERVER;
-      new_arg.type = GRPC_ARG_STRING;
-      new_arg.value.string = chand->server_name;
-      grpc_channel_args *tmp_args = chand->resolver_result;
-      chand->resolver_result =
-          grpc_channel_args_copy_and_add(chand->resolver_result, &new_arg, 1);
-      grpc_channel_args_destroy(exec_ctx, tmp_args);
-    }
     // Instantiate LB policy.
     grpc_lb_policy_args lb_policy_args;
     lb_policy_args.args = chand->resolver_result;
@@ -542,24 +527,21 @@
   GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
   grpc_client_channel_factory_ref(arg->value.pointer.p);
   chand->client_channel_factory = arg->value.pointer.p;
-  // Instantiate resolver.
+  // Get server name to resolve, using proxy mapper if needed.
   arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
   GPR_ASSERT(arg != NULL);
   GPR_ASSERT(arg->type == GRPC_ARG_STRING);
-  grpc_uri *uri = grpc_uri_parse(arg->value.string, true);
-  if (uri == NULL) return GRPC_ERROR_CREATE("cannot parse server URI");
-  if (uri->path[0] == '\0') {
-    grpc_uri_destroy(uri);
-    return GRPC_ERROR_CREATE("server URI is missing path");
-  }
-  chand->server_name =
-      gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
-  grpc_uri_destroy(uri);
-  chand->proxy_name = grpc_get_http_proxy_server();
-  char *name_to_resolve =
-      chand->proxy_name == NULL ? arg->value.string : chand->proxy_name;
+  char *proxy_name = NULL;
+  grpc_channel_args *new_args = NULL;
+  grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
+                              &proxy_name, &new_args);
+  // Instantiate resolver.
   chand->resolver = grpc_resolver_create(
-      exec_ctx, name_to_resolve, args->channel_args, chand->interested_parties);
+      exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
+      new_args != NULL ? new_args : args->channel_args,
+      chand->interested_parties);
+  if (proxy_name != NULL) gpr_free(proxy_name);
+  if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
   if (chand->resolver == NULL) {
     return GRPC_ERROR_CREATE("resolver creation failed");
   }
@@ -570,8 +552,6 @@
 static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
                                     grpc_channel_element *elem) {
   channel_data *chand = elem->channel_data;
-  gpr_free(chand->server_name);
-  gpr_free(chand->proxy_name);
   if (chand->resolver != NULL) {
     grpc_resolver_shutdown(exec_ctx, chand->resolver);
     GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
diff --git a/src/core/ext/client_channel/client_channel_plugin.c b/src/core/ext/client_channel/client_channel_plugin.c
index 7f75233..6f9df3e 100644
--- a/src/core/ext/client_channel/client_channel_plugin.c
+++ b/src/core/ext/client_channel/client_channel_plugin.c
@@ -39,6 +39,7 @@
 
 #include "src/core/ext/client_channel/client_channel.h"
 #include "src/core/ext/client_channel/http_connect_handshaker.h"
+#include "src/core/ext/client_channel/http_proxy.h"
 #include "src/core/ext/client_channel/lb_policy_registry.h"
 #include "src/core/ext/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
@@ -82,6 +83,7 @@
   grpc_lb_policy_registry_init();
   grpc_resolver_registry_init();
   grpc_proxy_mapper_registry_init();
+  grpc_register_http_proxy_mapper();
   grpc_subchannel_index_init();
   grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN,
                                    set_default_host_if_unset, NULL);
diff --git a/src/core/ext/client_channel/http_proxy.c b/src/core/ext/client_channel/http_proxy.c
index 9a6c818..7daa071 100644
--- a/src/core/ext/client_channel/http_proxy.c
+++ b/src/core/ext/client_channel/http_proxy.c
@@ -40,10 +40,13 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/ext/client_channel/http_connect_handshaker.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/client_channel/uri_parser.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/support/env.h"
 
-char* grpc_get_http_proxy_server() {
+static char* grpc_get_http_proxy_server() {
   char* uri_str = gpr_getenv("http_proxy");
   if (uri_str == NULL) return NULL;
   grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */);
@@ -66,3 +69,49 @@
   grpc_uri_destroy(uri);
   return proxy_name;
 }
+
+static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
+                                  grpc_proxy_mapper* mapper,
+                                  const char* server_uri,
+                                  const grpc_channel_args* args,
+                                  char** name_to_resolve,
+                                  grpc_channel_args** new_args) {
+  *name_to_resolve = grpc_get_http_proxy_server();
+  if (*name_to_resolve == NULL) return false;
+  grpc_uri* uri = grpc_uri_parse(server_uri, false /* suppress_errors */);
+  if (uri == NULL || uri->path[0] == '\0') {
+    gpr_log(GPR_ERROR,
+            "'http_proxy' environment variable set, but cannot "
+            "parse server URI '%s' -- not using proxy",
+            server_uri);
+    if (uri != NULL) grpc_uri_destroy(uri);
+    return false;
+  }
+  grpc_arg new_arg;
+  new_arg.key = GRPC_ARG_HTTP_CONNECT_SERVER;
+  new_arg.type = GRPC_ARG_STRING;
+  new_arg.value.string = uri->path[0] == '/' ? uri->path + 1 : uri->path;
+  *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
+  grpc_uri_destroy(uri);
+  return true;
+}
+
+static bool proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
+                                     grpc_proxy_mapper* mapper,
+                                     const grpc_resolved_address* address,
+                                     const grpc_channel_args* args,
+                                     grpc_resolved_address** new_address,
+                                     grpc_channel_args** new_args) {
+  return false;
+}
+
+static void proxy_mapper_destroy(grpc_proxy_mapper* mapper) {}
+
+static const grpc_proxy_mapper_vtable proxy_mapper_vtable = {
+    proxy_mapper_map_name, proxy_mapper_map_address, proxy_mapper_destroy};
+
+static grpc_proxy_mapper proxy_mapper = {&proxy_mapper_vtable};
+
+void grpc_register_http_proxy_mapper() {
+  grpc_proxy_mapper_register(true /* at_start */, &proxy_mapper);
+}
diff --git a/src/core/ext/client_channel/http_proxy.h b/src/core/ext/client_channel/http_proxy.h
index 0d77ae2..c8882b1 100644
--- a/src/core/ext/client_channel/http_proxy.h
+++ b/src/core/ext/client_channel/http_proxy.h
@@ -34,8 +34,6 @@
 #ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H
 #define GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H
 
-/// Returns the name of the proxy to use, or NULL if no proxy is configured.
-/// Caller takes ownership of result.
-char* grpc_get_http_proxy_server();
+void grpc_register_http_proxy_mapper();
 
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H */
diff --git a/src/core/ext/client_channel/proxy_mapper.c b/src/core/ext/client_channel/proxy_mapper.c
index 6b6f328..f92afe8 100644
--- a/src/core/ext/client_channel/proxy_mapper.c
+++ b/src/core/ext/client_channel/proxy_mapper.c
@@ -38,13 +38,24 @@
   mapper->vtable = vtable;
 }
 
-bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
-                           const grpc_resolved_address* address,
-                           const grpc_channel_args* args,
-                           grpc_resolved_address** new_address,
-                           grpc_channel_args** new_args) {
-  return mapper->vtable->map(exec_ctx, mapper, address, args, new_address,
-                             new_args);
+bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
+                                grpc_proxy_mapper* mapper,
+                                const char* server_uri,
+                                const grpc_channel_args* args,
+                                char** name_to_resolve,
+                                grpc_channel_args** new_args) {
+  return mapper->vtable->map_name(exec_ctx, mapper, server_uri, args,
+                                  name_to_resolve, new_args);
+}
+
+bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
+                                   grpc_proxy_mapper* mapper,
+                                   const grpc_resolved_address* address,
+                                   const grpc_channel_args* args,
+                                   grpc_resolved_address** new_address,
+                                   grpc_channel_args** new_args) {
+  return mapper->vtable->map_address(exec_ctx, mapper, address, args,
+                                     new_address, new_args);
 }
 
 void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper) {
diff --git a/src/core/ext/client_channel/proxy_mapper.h b/src/core/ext/client_channel/proxy_mapper.h
index fa93037..6e4607f 100644
--- a/src/core/ext/client_channel/proxy_mapper.h
+++ b/src/core/ext/client_channel/proxy_mapper.h
@@ -43,15 +43,22 @@
 typedef struct grpc_proxy_mapper grpc_proxy_mapper;
 
 typedef struct {
+  /// Determines the proxy name to resolve for \a server_uri.
+  /// If no proxy is needed, returns false.
+  /// Otherwise, sets \a name_to_resolve, optionally sets \a new_args,
+  /// and returns true.
+  bool (*map_name)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+                   const char* server_uri, const grpc_channel_args* args,
+                   char** name_to_resolve, grpc_channel_args** new_args);
   /// Determines the proxy address to use to contact \a address.
   /// If no proxy is needed, returns false.
   /// Otherwise, sets \a new_address, optionally sets \a new_args, and
   /// returns true.
-  bool (*map)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
-              const grpc_resolved_address* address,
-              const grpc_channel_args* args,
-              grpc_resolved_address** new_address,
-              grpc_channel_args** new_args);
+  bool (*map_address)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+                      const grpc_resolved_address* address,
+                      const grpc_channel_args* args,
+                      grpc_resolved_address** new_address,
+                      grpc_channel_args** new_args);
   /// Destroys \a mapper.
   void (*destroy)(grpc_proxy_mapper* mapper);
 } grpc_proxy_mapper_vtable;
@@ -63,11 +70,20 @@
 void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
                             grpc_proxy_mapper* mapper);
 
-bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
-                           const grpc_resolved_address* address,
-                           const grpc_channel_args* args,
-                           grpc_resolved_address** new_address,
-                           grpc_channel_args** new_args);
+bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
+                                grpc_proxy_mapper* mapper,
+                                const char* server_uri,
+                                const grpc_channel_args* args,
+                                char** name_to_resolve,
+                                grpc_channel_args** new_args);
+
+bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
+                                   grpc_proxy_mapper* mapper,
+                                   const grpc_resolved_address* address,
+                                   const grpc_channel_args* args,
+                                   grpc_resolved_address** new_address,
+                                   grpc_channel_args** new_args);
+
 void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H */
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.c b/src/core/ext/client_channel/proxy_mapper_registry.c
index 0a156c8..2c44b9d 100644
--- a/src/core/ext/client_channel/proxy_mapper_registry.c
+++ b/src/core/ext/client_channel/proxy_mapper_registry.c
@@ -61,15 +61,28 @@
   ++list->num_mappers;
 }
 
-static bool grpc_proxy_mapper_list_map(grpc_exec_ctx* exec_ctx,
-                                       grpc_proxy_mapper_list* list,
-                                       const grpc_resolved_address* address,
-                                       const grpc_channel_args* args,
-                                       grpc_resolved_address** new_address,
-                                       grpc_channel_args** new_args) {
+static bool grpc_proxy_mapper_list_map_name(grpc_exec_ctx* exec_ctx,
+                                            grpc_proxy_mapper_list* list,
+                                            const char* server_uri,
+                                            const grpc_channel_args* args,
+                                            char** name_to_resolve,
+                                            grpc_channel_args** new_args) {
   for (size_t i = 0; i < list->num_mappers; ++i) {
-    if (grpc_proxy_mapper_map(exec_ctx, list->list[i], address, args,
-                              new_address, new_args)) {
+    if (grpc_proxy_mapper_map_name(exec_ctx, list->list[i], server_uri, args,
+                                   name_to_resolve, new_args)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static bool grpc_proxy_mapper_list_map_address(
+    grpc_exec_ctx* exec_ctx, grpc_proxy_mapper_list* list,
+    const grpc_resolved_address* address, const grpc_channel_args* args,
+    grpc_resolved_address** new_address, grpc_channel_args** new_args) {
+  for (size_t i = 0; i < list->num_mappers; ++i) {
+    if (grpc_proxy_mapper_map_address(exec_ctx, list->list[i], address, args,
+                                      new_address, new_args)) {
       return true;
     }
   }
@@ -101,11 +114,20 @@
   grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper);
 }
 
-bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx,
-                            const grpc_resolved_address* address,
-                            const grpc_channel_args* args,
-                            grpc_resolved_address** new_address,
-                            grpc_channel_args** new_args) {
-  return grpc_proxy_mapper_list_map(exec_ctx, &g_proxy_mapper_list, address,
-                                    args, new_address, new_args);
+bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx,
+                                 const char* server_uri,
+                                 const grpc_channel_args* args,
+                                 char** name_to_resolve,
+                                 grpc_channel_args** new_args) {
+  return grpc_proxy_mapper_list_map_name(exec_ctx, &g_proxy_mapper_list,
+                                         server_uri, args, name_to_resolve,
+                                         new_args);
+}
+bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx,
+                                    const grpc_resolved_address* address,
+                                    const grpc_channel_args* args,
+                                    grpc_resolved_address** new_address,
+                                    grpc_channel_args** new_args) {
+  return grpc_proxy_mapper_list_map_address(
+      exec_ctx, &g_proxy_mapper_list, address, args, new_address, new_args);
 }
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.h b/src/core/ext/client_channel/proxy_mapper_registry.h
index b76af8d..742b57a 100644
--- a/src/core/ext/client_channel/proxy_mapper_registry.h
+++ b/src/core/ext/client_channel/proxy_mapper_registry.h
@@ -44,10 +44,16 @@
 /// the list.  Otherwise, it will be added to the end.
 void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper);
 
-bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx,
-                            const grpc_resolved_address* address,
-                            const grpc_channel_args* args,
-                            grpc_resolved_address** new_address,
-                            grpc_channel_args** new_args);
+bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx,
+                                 const char* server_uri,
+                                 const grpc_channel_args* args,
+                                 char** name_to_resolve,
+                                 grpc_channel_args** new_args);
+
+bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx,
+                                    const grpc_resolved_address* address,
+                                    const grpc_channel_args* args,
+                                    grpc_resolved_address** new_address,
+                                    grpc_channel_args** new_args);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */
diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c
index abbbfdf..aa036e8 100644
--- a/src/core/ext/client_channel/subchannel.c
+++ b/src/core/ext/client_channel/subchannel.c
@@ -336,8 +336,8 @@
   grpc_set_initial_connect_string(&addr, &c->initial_connect_string);
   grpc_resolved_address *new_address = NULL;
   grpc_channel_args *new_args = NULL;
-  if (grpc_proxy_mappers_map(exec_ctx, addr, args->args, &new_address,
-                             &new_args)) {
+  if (grpc_proxy_mappers_map_address(exec_ctx, addr, args->args, &new_address,
+                                     &new_args)) {
     GPR_ASSERT(new_address != NULL);
     gpr_free(addr);
     addr = new_address;