You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bn...@apache.org on 2026/08/26 19:57:50 UTC

(trafficserver) branch master updated: Restore host in unmapped URL logs (#13435)

This is an automated email from the ASF dual-hosted git repository.

bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 10b4fe3c76 Restore host in unmapped URL logs (#13435)
10b4fe3c76 is described below

commit 10b4fe3c764e0df609e20c922a8500ddaa3063eb
Author: Brian Neradt <br...@gmail.com>
AuthorDate: Wed Aug 26 14:57:45 2026 -0500

    Restore host in unmapped URL logs (#13435)
    
    Intercepted requests that skip remapping preserve an unmapped URL
    before the Host header is promoted. The valid but incomplete snapshot
    prevents logging from using its fallback and produces URLs such as
    http:///_stats.
    
    This promotes the request target into the unmapped URL when the
    snapshot is created, regardless of whether remapping will run. It also
    adds stats_over_http coverage for hostless cquuc output.
    
    Fixes: #11378
---
 src/proxy/http/HttpSM.cc                           | 22 ----------------------
 src/proxy/http/HttpTransact.cc                     |  3 ++-
 .../stats_over_http/stats_over_http.test.py        | 19 ++++++++++++++++++-
 3 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/src/proxy/http/HttpSM.cc b/src/proxy/http/HttpSM.cc
index ef942ddd88..c8f51fba8a 100644
--- a/src/proxy/http/HttpSM.cc
+++ b/src/proxy/http/HttpSM.cc
@@ -4690,28 +4690,6 @@ HttpSM::do_remap_request(bool run_inline)
 
   check_sni_host();
 
-  // Depending on a variety of factors the HOST field may or may not have been promoted to the
-  // client request URL. The unmapped URL should always have that promotion done. If the HOST field
-  // is not already there, promote it only in the unmapped_url. This avoids breaking any logic that
-  // depends on the lack of promotion in the client request URL.
-  if (!t_state.unmapped_url.m_url_impl->m_ptr_host) {
-    MIMEField *host_field = t_state.hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_HOST));
-    if (host_field) {
-      auto host_name{host_field->value_get()};
-      if (!host_name.empty()) {
-        int  port     = 0;
-        bool has_port = false;
-
-        if (http_parse_host_header(host_name, host_name, port, has_port)) {
-          t_state.unmapped_url.host_set(host_name);
-        }
-        if (has_port) {
-          t_state.unmapped_url.port_set(port);
-        }
-      }
-    }
-  }
-
   if (!ret) {
     SMDbg(dbg_ctl_url_rewrite, "Could not find a valid remapping entry for this request");
     Metrics::Counter::increment(http_rsb.no_remap_matched);
diff --git a/src/proxy/http/HttpTransact.cc b/src/proxy/http/HttpTransact.cc
index 779383f61f..b21c70c1e0 100644
--- a/src/proxy/http/HttpTransact.cc
+++ b/src/proxy/http/HttpTransact.cc
@@ -1088,9 +1088,10 @@ HttpTransact::HandleBlindTunnel(State *s)
 void
 HttpTransact::StartRemapRequest(State *s)
 {
-  // Preserve effective url before remap, regardless of actual need for remap
+  // Preserve the effective URL before remap, regardless of the actual need for remap.
   s->unmapped_url.create(s->hdr_info.client_request.url_get()->m_heap);
   s->unmapped_url.copy(s->hdr_info.client_request.url_get());
+  s->hdr_info.client_request.set_url_target_from_host_field(&s->unmapped_url);
 
   if (s->api_skip_all_remapping) {
     TxnDbg(dbg_ctl_http_trans, "API request to skip remapping");
diff --git a/tests/gold_tests/pluginTest/stats_over_http/stats_over_http.test.py b/tests/gold_tests/pluginTest/stats_over_http/stats_over_http.test.py
index a93ef0491c..532153f7e5 100644
--- a/tests/gold_tests/pluginTest/stats_over_http/stats_over_http.test.py
+++ b/tests/gold_tests/pluginTest/stats_over_http/stats_over_http.test.py
@@ -17,6 +17,7 @@
 #  limitations under the License.
 
 from enum import Enum
+import os
 import re
 import sys
 
@@ -48,12 +49,28 @@ class StatsOverHttpPluginTest:
         self.ts = Test.MakeATSProcess("ts")
 
         self.ts.Disk.plugin_config.AddLine('stats_over_http.so _stats')
+        self.ts.Disk.logging_yaml.AddLines(
+            '''
+logging:
+  formats:
+    - name: unmapped_url
+      format: "%<cquuc>"
+  logs:
+    - filename: stats_over_http_url
+      format: unmapped_url
+'''.split("\n"))
+        self.ts.Disk.File(os.path.join(self.ts.Variables.LOGDIR, 'stats_over_http_url.log'), id='unmapped_url_log')
+        self.ts.Disk.unmapped_url_log.Content += Testers.ContainsExpression(
+            rf'http://127\.0\.0\.1:{self.ts.Variables.port}/_stats', 'The unmapped URL should contain the Host header value.')
+        self.ts.Disk.unmapped_url_log.Content += Testers.ExcludesExpression(
+            'http:///', 'The unmapped URL should not omit the request host.')
 
         self.ts.Disk.records_config.update(
             {
                 "proxy.config.http.server_ports": f"{self.ts.Variables.port} {self.ts.Variables.uds_path}",
                 "proxy.config.diags.debug.enabled": 1,
-                "proxy.config.diags.debug.tags": "stats_over_http"
+                "proxy.config.diags.debug.tags": "stats_over_http",
+                "proxy.config.log.max_secs_per_buffer": 1,
             })
 
     def __checkProcessBefore(self, tr):