Add host_override NH option (#9984)
sets the host header to the upstream parent instead of the original request
diff --git a/doc/admin-guide/files/strategies.yaml.en.rst b/doc/admin-guide/files/strategies.yaml.en.rst
index f5b8443..19353d0 100644
--- a/doc/admin-guide/files/strategies.yaml.en.rst
+++ b/doc/admin-guide/files/strategies.yaml.en.rst
@@ -230,6 +230,8 @@
     (**self** should only be necessary when the local hostname can only be translated to an IP address
     with a DNS lookup.)
 
+- **host_override**: A boolean value that will set the host header to the selected parent rather than the original host. **true** sets host header to selected parent. **false** (default) leaves the host header untouched.
+
 Example:
 ::
 
@@ -254,6 +256,7 @@
           - passive
     - strategy: 'strategy-2'
       policy: rr_strict
+      host_override: true
       hash_url: cache
       hash_key: path+query
       go_direct: true
diff --git a/proxy/http/remap/NextHopConsistentHash.cc b/proxy/http/remap/NextHopConsistentHash.cc
index fe23dbe..51a14ed 100644
--- a/proxy/http/remap/NextHopConsistentHash.cc
+++ b/proxy/http/remap/NextHopConsistentHash.cc
@@ -496,5 +496,7 @@
              ParentResultStr[result.result]);
   }
 
+  setHostHeader(txnp, result.hostname);
+
   return;
 }
diff --git a/proxy/http/remap/NextHopRoundRobin.cc b/proxy/http/remap/NextHopRoundRobin.cc
index f2e8725..508228e 100644
--- a/proxy/http/remap/NextHopRoundRobin.cc
+++ b/proxy/http/remap/NextHopRoundRobin.cc
@@ -171,6 +171,7 @@
       result->last_parent = cur_hst_index;
       result->last_group  = cur_grp_index;
       result->retry       = parentRetry;
+      setHostHeader(txnp, result->hostname);
       ink_assert(result->hostname != nullptr);
       ink_assert(result->port != 0);
       NH_Debug(NH_DEBUG_TAG, "[%" PRIu64 "] Chosen parent = %s.%d", sm_id, result->hostname, result->port);
diff --git a/proxy/http/remap/NextHopSelectionStrategy.cc b/proxy/http/remap/NextHopSelectionStrategy.cc
index a924c87..bb8482a 100644
--- a/proxy/http/remap/NextHopSelectionStrategy.cc
+++ b/proxy/http/remap/NextHopSelectionStrategy.cc
@@ -82,6 +82,10 @@
       cache_peer_result = n["cache_peer_result"].as<bool>();
     }
 
+    if (n["host_override"]) {
+      host_override = n["host_override"].as<bool>();
+    }
+
     // failover node.
     YAML::Node failover_node_n = n["failover"];
     if (failover_node_n) {
@@ -255,6 +259,16 @@
   return passive_health.markNextHop(txnp, hostname, port, status, ih, now);
 }
 
+void
+NextHopSelectionStrategy::setHostHeader(TSHttpTxn txnp, const char *hostname)
+{
+  if (host_override && nullptr != hostname) {
+    HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
+    sm->t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, hostname, strlen(hostname));
+    NH_Debug(NH_DEBUG_TAG, "[%" PRIu64 "] overriding host header with parent %s", sm->sm_id, hostname);
+  }
+}
+
 bool
 NextHopSelectionStrategy::nextHopExists(TSHttpTxn txnp, void *ih)
 {
diff --git a/proxy/http/remap/NextHopSelectionStrategy.h b/proxy/http/remap/NextHopSelectionStrategy.h
index 1fe49cb..d327acd 100644
--- a/proxy/http/remap/NextHopSelectionStrategy.h
+++ b/proxy/http/remap/NextHopSelectionStrategy.h
@@ -202,6 +202,8 @@
                    const time_t now = 0);
   bool nextHopExists(TSHttpTxn txnp, void *ih = nullptr);
 
+  void setHostHeader(TSHttpTxn txnp, const char *hostname);
+
   virtual ParentRetry_t responseIsRetryable(int64_t sm_id, HttpTransact::CurrentInfo ¤t_info, HTTPStatus response_code);
 
   void retryComplete(TSHttpTxn txn, const char *hostname, const int port);
@@ -211,6 +213,7 @@
   bool parent_is_proxy     = true;
   bool ignore_self_detect  = false;
   bool cache_peer_result   = true;
+  bool host_override       = false;
   NHPolicyType policy_type = NH_UNDEFINED;
   NHSchemeType scheme      = NH_SCHEME_NONE;
   NHRingMode ring_mode     = NH_ALTERNATE_RING;