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 46413e8303 header_rewrite: Improve URL Error messages (#13261)
46413e8303 is described below

commit 46413e8303cd8467c4f8267fb529e00e0472b58e
Author: Brian Neradt <[email protected]>
AuthorDate: Tue Jun 23 12:56:43 2026 -0500

    header_rewrite: Improve URL Error messages (#13261)
    
    Old log:
    ERROR: [header_rewrite] Rule not supported at this hook
    
    New log:
    ERROR: [header_rewrite] Rule not supported at 
hook=TS_HTTP_READ_RESPONSE_HDR_HOOK: %{TO-URL:URL} in 
/tmp/sb/header_rewrite_unsupported_url_hook/unsupported_url_hook.conf:18
---
 plugins/header_rewrite/conditions.cc | 58 ++++++++++++++++++++++++++++++++----
 plugins/header_rewrite/conditions.h  |  2 ++
 plugins/header_rewrite/operators.cc  |  2 ++
 plugins/header_rewrite/resources.cc  |  1 +
 plugins/header_rewrite/resources.h   |  1 +
 plugins/header_rewrite/ruleset.cc    |  2 ++
 plugins/header_rewrite/statement.h   | 29 +++++++++++++++++-
 plugins/header_rewrite/value.cc      |  6 ++++
 8 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/plugins/header_rewrite/conditions.cc 
b/plugins/header_rewrite/conditions.cc
index 3d32c3515d..1953864d79 100644
--- a/plugins/header_rewrite/conditions.cc
+++ b/plugins/header_rewrite/conditions.cc
@@ -39,6 +39,42 @@
 
 static const sockaddr *getClientAddr(TSHttpTxn txnp, int txn_private_slot);
 
+static const char *
+get_hook_name(TSHttpHookID hook)
+{
+  if (hook == TS_REMAP_PSEUDO_HOOK) {
+    return "REMAP_PSEUDO_HOOK";
+  }
+
+  if (hook == TS_HTTP_LAST_HOOK) {
+    return "UNKNOWN_HOOK";
+  }
+
+  if (const char *name = TSHttpHookNameLookup(hook); name != nullptr) {
+    return name;
+  }
+
+  return "UNKNOWN_HOOK";
+}
+
+static const char *
+get_url_type_name(ConditionUrl::UrlType type)
+{
+  switch (type) {
+  case ConditionUrl::CLIENT:
+    return "CLIENT-URL";
+  case ConditionUrl::SERVER:
+    return "SERVER-URL";
+  case ConditionUrl::FROM:
+    return "FROM-URL";
+  case ConditionUrl::TO:
+    return "TO-URL";
+  case ConditionUrl::URL:
+  default:
+    return "URL";
+  }
+}
+
 #if TS_HAS_CRIPTS
 #include "cripts/Certs.hpp"
 #endif
@@ -318,6 +354,18 @@ ConditionUrl::set_qualifier(const std::string &q)
   }
 }
 
+void
+ConditionUrl::log_error(const Resources &res, const char *message) const
+{
+  if (has_config_location()) {
+    TSError("[%s] %s at hook=%s: %%{%s%s%s} in %s:%d", PLUGIN_NAME, message, 
get_hook_name(res.hook), get_url_type_name(_type),
+            _qualifier.empty() ? "" : ":", _qualifier.c_str(), 
get_config_filename().c_str(), get_config_lineno());
+  } else {
+    TSError("[%s] %s at hook=%s: %%{%s%s%s}", PLUGIN_NAME, message, 
get_hook_name(res.hook), get_url_type_name(_type),
+            _qualifier.empty() ? "" : ":", _qualifier.c_str());
+  }
+}
+
 void
 ConditionUrl::append_value(std::string &s, const Resources &res)
 {
@@ -328,7 +376,7 @@ ConditionUrl::append_value(std::string &s, const Resources 
&res)
     // CLIENT always uses the pristine URL
     Dbg(pi_dbg_ctl, "   Using the pristine url");
     if (TSHttpTxnPristineUrlGet(res.state.txnp, &bufp, &url) != TS_SUCCESS) {
-      TSError("[%s] Error getting the pristine URL", PLUGIN_NAME);
+      log_error(res, "Error getting the pristine URL");
       return;
     }
   } else if (_type == SERVER) {
@@ -336,7 +384,7 @@ ConditionUrl::append_value(std::string &s, const Resources 
&res)
     bufp = res.server_bufp;
     if (bufp && res.server_hdr_loc) {
       if (TSHttpHdrUrlGet(bufp, res.server_hdr_loc, &url) != TS_SUCCESS) {
-        TSError("[%s] Error getting the server request URL", PLUGIN_NAME);
+        log_error(res, "Error getting the server request URL");
         return;
       }
     } else {
@@ -356,7 +404,7 @@ ConditionUrl::append_value(std::string &s, const Resources 
&res)
       Dbg(pi_dbg_ctl, "   Using the to url");
       url = res._rri->mapToUrl;
     } else {
-      TSError("[%s] Invalid option value", PLUGIN_NAME);
+      log_error(res, "Invalid URL option value");
       return;
     }
   } else {
@@ -364,11 +412,11 @@ ConditionUrl::append_value(std::string &s, const 
Resources &res)
       bufp           = res.bufp;
       TSMLoc hdr_loc = res.hdr_loc;
       if (TSHttpHdrUrlGet(bufp, hdr_loc, &url) != TS_SUCCESS) {
-        TSError("[%s] Error getting the URL", PLUGIN_NAME);
+        log_error(res, "Error getting the URL");
         return;
       }
     } else {
-      TSError("[%s] Rule not supported at this hook", PLUGIN_NAME);
+      log_error(res, "Rule not supported");
       return;
     }
   }
diff --git a/plugins/header_rewrite/conditions.h 
b/plugins/header_rewrite/conditions.h
index 631854e8f4..65020646b8 100644
--- a/plugins/header_rewrite/conditions.h
+++ b/plugins/header_rewrite/conditions.h
@@ -300,6 +300,8 @@ protected:
   bool eval(const Resources &res) override;
 
 private:
+  void log_error(const Resources &res, const char *message) const;
+
   UrlQualifiers _url_qual = URL_QUAL_NONE;
   UrlType       _type;
   std::string   _query_param; // Optional: specific query parameter name for 
QUERY sub-key
diff --git a/plugins/header_rewrite/operators.cc 
b/plugins/header_rewrite/operators.cc
index 2913c9349f..e82b834468 100644
--- a/plugins/header_rewrite/operators.cc
+++ b/plugins/header_rewrite/operators.cc
@@ -1720,6 +1720,7 @@ OperatorIf::add_operator(Parser &p, const char *filename, 
int lineno)
   }
 
   Dbg(pi_dbg_ctl, "    Adding operator: %s(%s)=\"%s\"", p.get_op().c_str(), 
p.get_arg().c_str(), p.get_value().c_str());
+  op->set_config_location(filename, lineno);
 
   try {
     op->initialize(p);
@@ -1752,6 +1753,7 @@ OperatorIf::make_condition(Parser &p, const char 
*filename, int lineno)
   }
 
   Dbg(pi_dbg_ctl, "    Creating condition: %%{%s} with arg: %s", 
p.get_op().c_str(), p.get_arg().c_str());
+  cond->set_config_location(filename, lineno);
 
   try {
     cond->initialize(p);
diff --git a/plugins/header_rewrite/resources.cc 
b/plugins/header_rewrite/resources.cc
index 78450147b9..ed8d4ffe6a 100644
--- a/plugins/header_rewrite/resources.cc
+++ b/plugins/header_rewrite/resources.cc
@@ -32,6 +32,7 @@
 void
 Resources::gather(const ResourceIDs ids, TSHttpHookID hook)
 {
+  this->hook = hook;
   Dbg(pi_dbg_ctl, "Building resources, hook=%s", TSHttpHookNameLookup(hook));
   Dbg(pi_dbg_ctl, "Gathering resources for hook %s with IDs %d", 
TSHttpHookNameLookup(hook), ids);
 
diff --git a/plugins/header_rewrite/resources.h 
b/plugins/header_rewrite/resources.h
index 80d1268106..d745dffdee 100644
--- a/plugins/header_rewrite/resources.h
+++ b/plugins/header_rewrite/resources.h
@@ -128,6 +128,7 @@ public:
 #endif
   TSHttpStatus resp_status = TS_HTTP_STATUS_NONE;
   void        *geo_handle  = nullptr;
+  TSHttpHookID hook        = TS_HTTP_LAST_HOOK;
 
   struct LifetimeExtension {
     std::string                                        subject_storage;
diff --git a/plugins/header_rewrite/ruleset.cc 
b/plugins/header_rewrite/ruleset.cc
index 28fda37a51..39964fc68e 100644
--- a/plugins/header_rewrite/ruleset.cc
+++ b/plugins/header_rewrite/ruleset.cc
@@ -65,6 +65,7 @@ RuleSet::make_condition(Parser &p, const char *filename, int 
lineno)
   }
 
   Dbg(pi_dbg_ctl, "    Creating condition: %%{%s} with arg: %s", 
p.get_op().c_str(), p.get_arg().c_str());
+  c->set_config_location(filename, lineno);
   c->initialize(p);
   if (!c->set_hook(_hook)) {
     delete c;
@@ -92,6 +93,7 @@ RuleSet::add_operator(Parser &p, const char *filename, int 
lineno)
 
   if (nullptr != op) {
     Dbg(pi_dbg_ctl, "    Adding operator: %s(%s)=\"%s\"", p.get_op().c_str(), 
p.get_arg().c_str(), p.get_value().c_str());
+    op->set_config_location(filename, lineno);
     op->initialize(p);
     if (!op->set_hook(_hook)) {
       delete op;
diff --git a/plugins/header_rewrite/statement.h 
b/plugins/header_rewrite/statement.h
index 1f16c24246..4ed73ec681 100644
--- a/plugins/header_rewrite/statement.h
+++ b/plugins/header_rewrite/statement.h
@@ -172,6 +172,31 @@ public:
 
   ResourceIDs get_resource_ids() const;
 
+  void
+  set_config_location(const char *filename, int lineno)
+  {
+    _config_filename = filename ? filename : "";
+    _config_lineno   = lineno;
+  }
+
+  bool
+  has_config_location() const
+  {
+    return !_config_filename.empty();
+  }
+
+  const std::string &
+  get_config_filename() const
+  {
+    return _config_filename;
+  }
+
+  int
+  get_config_lineno() const
+  {
+    return _config_lineno;
+  }
+
   virtual void
   initialize(Parser &)
   {
@@ -277,7 +302,9 @@ private:
   ResourceIDs               _rsrc = RSRC_NONE;
   TSHttpHookID              _hook = TS_HTTP_READ_RESPONSE_HDR_HOOK;
   std::vector<TSHttpHookID> _allowed_hooks;
-  bool                      _initialized = false;
+  std::string               _config_filename;
+  int                       _config_lineno = 0;
+  bool                      _initialized   = false;
 };
 
 union PrivateSlotData {
diff --git a/plugins/header_rewrite/value.cc b/plugins/header_rewrite/value.cc
index 70fd17893a..38b00dd825 100644
--- a/plugins/header_rewrite/value.cc
+++ b/plugins/header_rewrite/value.cc
@@ -39,6 +39,9 @@ void
 Value::set_value(const std::string &val, Statement *owner)
 {
   _value = val;
+  if (owner && owner->has_config_location()) {
+    set_config_location(owner->get_config_filename().c_str(), 
owner->get_config_lineno());
+  }
 
   if (_value.find("%{") != std::string::npos) {
     HRWSimpleTokenizer tokenizer(_value);
@@ -54,6 +57,9 @@ Value::set_value(const std::string &val, Statement *owner)
           Parser parser;
 
           if (parser.parse_line(cond_token)) {
+            if (has_config_location()) {
+              tcond_val->set_config_location(get_config_filename().c_str(), 
get_config_lineno());
+            }
             tcond_val->initialize(parser);
             require_resources(tcond_val->get_resource_ids());
           } else {

Reply via email to