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

cmcfarlen pushed a commit to branch 10.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit f015c3e45b8dfb7f3b58291c49774b8671a32fe6
Author: Leif Hedstrom <[email protected]>
AuthorDate: Mon Jun 3 16:57:55 2024 -0600

    HRW: Adds an optional list of query params to remove/keep (#11384)
    
    (cherry picked from commit cb6dd9f3ed12f7efc345734825edd312d2aa1072)
---
 doc/admin-guide/plugins/header_rewrite.en.rst | 19 +++++++
 plugins/header_rewrite/operator.cc            |  6 ++-
 plugins/header_rewrite/operator.h             |  1 +
 plugins/header_rewrite/operators.cc           | 71 +++++++++++++++++++++------
 plugins/header_rewrite/operators.h            |  5 +-
 5 files changed, 86 insertions(+), 16 deletions(-)

diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst 
b/doc/admin-guide/plugins/header_rewrite.en.rst
index fe4db67e71..c7e34981a6 100644
--- a/doc/admin-guide/plugins/header_rewrite.en.rst
+++ b/doc/admin-guide/plugins/header_rewrite.en.rst
@@ -774,6 +774,14 @@ changing the remapped destination, ``<part>`` should be 
used to indicate the
 component that is being modified (see `URL Parts`_). Currently the only valid
 parts for rm-destination are QUERY, PATH, and PORT.
 
+For the query parameter, this operator takes an optional second argument,
+which is a list of query parameters to remove (or keep with ``[INV]`` 
modifier).
+
+::
+
+  rm-destination QUERY <comma separate list of query parameter>
+
+
 run-plugin
 ~~~~~~~~~~~~~~
 ::
@@ -898,6 +906,7 @@ The flags currently supported are:
 Flag   Description
 ====== ========================================================================
 L      Last rule, do not continue.
+I      Invert the semantics of the rules parameters
 QSA    Append the results of the rule to the query string.
 ====== ========================================================================
 
@@ -1332,6 +1341,16 @@ The following ruleset removes any query parameters set 
by the client.::
    cond %{REMAP_PSEUDO_HOOK}
    rm-destination QUERY
 
+Remove only a few select query parameters:
+
+   cond %{REMAP_PSEUDO_HOOK}
+   rm-destination QUERY foo,bar
+
+Keep only a few select query parameters -- removing the rest:
+
+   cond %{REMAP_PSEUDO_HOOK}
+   rm-destination QUERY foo,bar [I]
+
 Mimic X-Debug Plugin's X-Cache Header
 -------------------------------------
 
diff --git a/plugins/header_rewrite/operator.cc 
b/plugins/header_rewrite/operator.cc
index 4788b2d0f2..4cd337ca4b 100644
--- a/plugins/header_rewrite/operator.cc
+++ b/plugins/header_rewrite/operator.cc
@@ -38,13 +38,17 @@ Operator::initialize(Parser &p)
 {
   Statement::initialize(p);
 
-  if (p.mod_exist("L")) {
+  if (p.mod_exist("L") || p.mod_exist("LAST")) {
     _mods = static_cast<OperModifiers>(_mods | OPER_LAST);
   }
 
   if (p.mod_exist("QSA")) {
     _mods = static_cast<OperModifiers>(_mods | OPER_QSA);
   }
+
+  if (p.mod_exist("I") || p.mod_exist("INV")) {
+    _mods = static_cast<OperModifiers>(_mods | OPER_INV);
+  }
 }
 
 void
diff --git a/plugins/header_rewrite/operator.h 
b/plugins/header_rewrite/operator.h
index 27e800fa62..250da57726 100644
--- a/plugins/header_rewrite/operator.h
+++ b/plugins/header_rewrite/operator.h
@@ -35,6 +35,7 @@ enum OperModifiers {
   OPER_LAST = 1,
   OPER_NEXT = 2,
   OPER_QSA  = 4,
+  OPER_INV  = 8,
 };
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/header_rewrite/operators.cc 
b/plugins/header_rewrite/operators.cc
index f6f96b15f1..b22f04253a 100644
--- a/plugins/header_rewrite/operators.cc
+++ b/plugins/header_rewrite/operators.cc
@@ -173,17 +173,6 @@ OperatorSetDestination::initialize(Parser &p)
   require_resources(RSRC_SERVER_REQUEST_HEADERS);
 }
 
-// OperatorRMDestination
-void
-OperatorRMDestination::initialize(Parser &p)
-{
-  Operator::initialize(p);
-
-  _url_qual = parse_url_qualifier(p.get_arg());
-  require_resources(RSRC_CLIENT_REQUEST_HEADERS);
-  require_resources(RSRC_SERVER_REQUEST_HEADERS);
-}
-
 void
 OperatorSetDestination::exec(const Resources &res) const
 {
@@ -293,12 +282,45 @@ OperatorSetDestination::exec(const Resources &res) const
   }
 }
 
+#include <iostream>
+
+// OperatorRMDestination
+static std::vector<std::string_view>
+_tokenize(swoc::TextView text, char delimiter)
+{
+  std::vector<std::string_view> tokens;
+
+  while (text) {
+    tokens.push_back(text.take_prefix_at(delimiter));
+  }
+
+  return tokens;
+}
+
+void
+OperatorRMDestination::initialize(Parser &p)
+{
+  Operator::initialize(p);
+
+  _url_qual = parse_url_qualifier(p.get_arg());
+  _stop     = p.get_value();
+
+  if (!_stop.empty()) {
+    if (get_oper_modifiers() & OPER_INV) {
+      _keep = true;
+    }
+    _stop_list = _tokenize(_stop, ',');
+  }
+
+  require_resources(RSRC_CLIENT_REQUEST_HEADERS);
+  require_resources(RSRC_SERVER_REQUEST_HEADERS);
+}
+
 void
 OperatorRMDestination::exec(const Resources &res) const
 {
   if (res._rri || (res.bufp && res.hdr_loc)) {
-    // Default empty string to delete components
-    static std::string value = "";
+    std::string value = "";
 
     // Determine which TSMBuffer and TSMLoc to use
     TSMBuffer bufp;
@@ -322,9 +344,30 @@ OperatorRMDestination::exec(const Resources &res) const
       Dbg(pi_dbg_ctl, "OperatorRMDestination::exec() deleting PATH");
       break;
     case URL_QUAL_QUERY:
+      if (_stop_list.size() > 0) {
+        int         q_len = 0;
+        const char *query = TSUrlHttpQueryGet(bufp, url_m_loc, &q_len);
+
+        if (q_len > 0) {
+          for (auto &q : _tokenize({query, static_cast<size_t>(q_len)}, '&')) {
+            auto eq_pos = q.find('=');
+            auto it = std::find(_stop_list.begin(), _stop_list.end(), (eq_pos 
!= std::string_view::npos) ? q.substr(0, eq_pos) : q);
+
+            if (_keep == (it != _stop_list.end())) {
+              if (!value.empty()) {
+                value.append("&").append(q);
+              } else {
+                value = q;
+              }
+            }
+          }
+        }
+        Dbg(pi_dbg_ctl, "OperatorRMDestination::exec() rewrote QUERY to 
\"%s\"", value.c_str());
+      } else {
+        Dbg(pi_dbg_ctl, "OperatorRMDestination::exec() deleting QUERY");
+      }
       const_cast<Resources &>(res).changed_url = true;
       TSUrlHttpQuerySet(bufp, url_m_loc, value.c_str(), value.size());
-      Dbg(pi_dbg_ctl, "OperatorRMDestination::exec() deleting QUERY");
       break;
     case URL_QUAL_PORT:
       const_cast<Resources &>(res).changed_url = true;
diff --git a/plugins/header_rewrite/operators.h 
b/plugins/header_rewrite/operators.h
index 3f30d2654d..dc7b19ee4a 100644
--- a/plugins/header_rewrite/operators.h
+++ b/plugins/header_rewrite/operators.h
@@ -129,7 +129,10 @@ protected:
   void exec(const Resources &res) const override;
 
 private:
-  UrlQualifiers _url_qual = URL_QUAL_NONE;
+  UrlQualifiers                 _url_qual = URL_QUAL_NONE;
+  bool                          _keep     = false;
+  std::string                   _stop     = "";
+  std::vector<std::string_view> _stop_list;
 };
 
 class OperatorSetRedirect : public Operator

Reply via email to