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

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

commit cbaceb52546873d7579b8b78e853f81d851504ae
Author: Masaori Koshiba <masa...@apache.org>
AuthorDate: Mon Aug 25 09:37:58 2025 +0900

    [cache_promote] Add --disable-on-redirect option (#12457)
    
    (cherry picked from commit fc2031dfc8682fcae9408ec18089c290e1acfde2)
---
 doc/admin-guide/plugins/cache_promote.en.rst       |   5 +
 plugins/cache_promote/cache_promote.cc             |   5 +
 plugins/cache_promote/configs.cc                   |   3 +
 plugins/cache_promote/configs.h                    |   7 +
 .../pluginTest/cache_promote/cache_promote.test.py |  77 ++++++++++
 .../replay/cache_promote.replay.yaml.tmpl          | 166 +++++++++++++++++++++
 6 files changed, 263 insertions(+)

diff --git a/doc/admin-guide/plugins/cache_promote.en.rst 
b/doc/admin-guide/plugins/cache_promote.en.rst
index 62da01ca06..975894f05c 100644
--- a/doc/admin-guide/plugins/cache_promote.en.rst
+++ b/doc/admin-guide/plugins/cache_promote.en.rst
@@ -39,6 +39,11 @@ are available:
 
    The sampling rate for the request to be considered
 
+.. option:: --disable-on-redirect
+
+   Disables running on ``TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK`` again when a 
transaction follows redirect.
+   This option is recommended when this plugin is used with the 
:program:`cachekey` plugin.
+
 If :option:`--policy` is set to ``lru`` the following options are also 
available:
 
 .. option:: --label
diff --git a/plugins/cache_promote/cache_promote.cc 
b/plugins/cache_promote/cache_promote.cc
index 21cba7cadc..4c3fccbe9c 100644
--- a/plugins/cache_promote/cache_promote.cc
+++ b/plugins/cache_promote/cache_promote.cc
@@ -52,6 +52,11 @@ cont_handle_policy(TSCont contp, TSEvent event, void *edata)
   switch (event) {
   // After the cache lookups check if it should be promoted on cache misses
   case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE:
+    if (TSHttpTxnRedirectRetries(txnp) > 0 && 
config->is_disabled_on_redirect()) {
+      // do nothing when following redirect if it's configured
+      break;
+    }
+
     if (!TSHttpTxnIsInternal(txnp) || 
config->getPolicy()->isInternalEnabled()) {
       int obj_status;
 
diff --git a/plugins/cache_promote/configs.cc b/plugins/cache_promote/configs.cc
index 58907125c3..a9d8b96092 100644
--- a/plugins/cache_promote/configs.cc
+++ b/plugins/cache_promote/configs.cc
@@ -27,6 +27,7 @@
 static const struct option longopt[] = {
   {const_cast<char *>("policy"),               required_argument, nullptr, 'p' 
},
   {const_cast<char *>("stats-enable-with-id"), required_argument, nullptr, 'e' 
},
+  {const_cast<char *>("disable-on-redirect"),  no_argument,       nullptr, 'd' 
},
   // This is for both Chance and LRU (optional) policy
   {const_cast<char *>("sample"),               required_argument, nullptr, 's' 
},
   // For the LRU policy
@@ -78,6 +79,8 @@ PromotionConfig::factory(int argc, char *argv[])
           DBG("stats collection is enabled");
         }
       }
+    } else if (opt == 'd') {
+      _disable_on_redirect = true;
     } else {
       if (_policy) {
         // The --sample (-s) option is allowed for all configs, but only after 
--policy is specified.
diff --git a/plugins/cache_promote/configs.h b/plugins/cache_promote/configs.h
index bbb9170497..f61f16b22c 100644
--- a/plugins/cache_promote/configs.h
+++ b/plugins/cache_promote/configs.h
@@ -38,7 +38,14 @@ public:
 
   bool factory(int argc, char *argv[]);
 
+  bool
+  is_disabled_on_redirect()
+  {
+    return _disable_on_redirect;
+  }
+
 private:
   PromotionPolicy *_policy = nullptr;
   PolicyManager   *_manager;
+  bool             _disable_on_redirect = false;
 };
diff --git a/tests/gold_tests/pluginTest/cache_promote/cache_promote.test.py 
b/tests/gold_tests/pluginTest/cache_promote/cache_promote.test.py
new file mode 100644
index 0000000000..7f4096171d
--- /dev/null
+++ b/tests/gold_tests/pluginTest/cache_promote/cache_promote.test.py
@@ -0,0 +1,77 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the #  "License"); you may 
not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+import os
+
+Test.Summary = '''
+Test cache_promote plugin
+'''
+
+Test.SkipUnless(Condition.PluginExists('cache_promote.so'))
+
+
+class CachePromotePluginTest:
+
+    def __init__(self):
+        self._tr = Test.AddTestRun("cache_promote")
+        self.__setupOriginServer()
+        self.__setupTS()
+        self.__setupClient()
+
+    def __setupClient(self):
+        # Eval template file to set origin server port to redirect
+        template_file_path = os.path.join(self._tr.TestDirectory, 
"replay/cache_promote.replay.yaml.tmpl")
+        with open(template_file_path, 'r') as f:
+            template = f.read()
+
+        replay_yaml_path = os.path.join(self._tr.RunDirectory, 
"cache_promote.replay.yaml")
+        with open(replay_yaml_path, 'w') as f:
+            f.write(template.format(httpbin_port=self._httpbin.Variables.Port))
+
+        self._tr.AddVerifierClientProcess("verifier-client", replay_yaml_path, 
http_ports=[self._ts.Variables.port])
+
+    def __setupOriginServer(self):
+        self._httpbin = Test.MakeHttpBinServer("httpbin")
+
+    def __setupTS(self):
+        self._ts = Test.MakeATSProcess("ts", enable_cache=True)
+        self._ts.Disk.records_config.update(
+            {
+                "proxy.config.diags.debug.enabled": 1,
+                "proxy.config.diags.debug.tags": "http|cache_promote",
+                "proxy.config.http.number_of_redirections": 1,  # follow 
redirect
+                "proxy.config.http.redirect.actions": "self:follow",  # 
redirects to self are not followed by default
+            })
+        self._ts.Disk.plugin_config.AddLine("xdebug.so 
--enable=x-cache,x-cache-key")
+        self._ts.Disk.remap_config.AddLines(
+            {
+                f"""
+map /test_0/ http://127.0.0.1:{self._httpbin.Variables.Port}/ \
+    @plugin=cache_promote.so @pparam=--policy=lru @pparam=--hits=2 
@pparam=--buckets=15000000
+
+map /test_1/ http://127.0.0.1:{self._httpbin.Variables.Port}/ \
+    @plugin=cache_promote.so @pparam=--policy=lru @pparam=--hits=2 
@pparam=--buckets=15000000 @pparam=--disable-on-redirect \
+    @plugin=cachekey.so @pparam=--static-prefix=trafficserver.apache.org/443
+"""
+            })
+
+    def run(self):
+        self._tr.Processes.Default.StartBefore(self._ts)
+        self._tr.Processes.Default.StartBefore(self._httpbin)
+        self._tr.StillRunningAfter = self._ts
+        self._tr.StillRunningAfter = self._httpbin
+
+
+CachePromotePluginTest().run()
diff --git 
a/tests/gold_tests/pluginTest/cache_promote/replay/cache_promote.replay.yaml.tmpl
 
b/tests/gold_tests/pluginTest/cache_promote/replay/cache_promote.replay.yaml.tmpl
new file mode 100644
index 0000000000..422da45cdf
--- /dev/null
+++ 
b/tests/gold_tests/pluginTest/cache_promote/replay/cache_promote.replay.yaml.tmpl
@@ -0,0 +1,166 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+#
+#  This is a template file to generate "cache_promote.replay.yaml" needs to be 
evaluated.
+#
+meta:
+  version: "1.0"
+
+sessions:
+- protocol:
+  - name: http
+    version: 1
+  - name: tcp
+  - name: ip
+
+  transactions:
+  #
+  # test case 0-0 : simple LRU policy case - 3rd request is expected to hit 
the cache
+  #
+  - client-request:
+      method: "GET"
+      url: /test_0/cache/2
+      headers:
+        fields:
+          - [ uuid, 0-0-0 ]
+          - [ x-debug, x-cache ]
+
+    proxy-response:
+      status: 200
+      headers:
+        fields:
+        - [ x-cache, {{value: "miss", as: equal }} ]
+
+  - client-request:
+      method: "GET"
+      url: /test_0/cache/2
+      headers:
+        fields:
+          - [ uuid, 0-0-1 ]
+          - [ x-debug, x-cache ]
+
+    proxy-response:
+      status: 200
+      headers:
+        fields:
+        - [ x-cache, {{value: "miss", as: equal }} ]
+
+  - client-request:
+      method: "GET"
+      url: /test_0/cache/2
+      headers:
+        fields:
+          - [ uuid, 0-0-2 ]
+          - [ x-debug, x-cache ]
+
+    proxy-response:
+      status: 200
+      headers:
+        fields:
+        - [ x-cache, {{value: "hit-fresh", as: equal }} ]
+
+  #
+  # test case 0-1 : following redirect
+  #
+  - client-request:
+      method: "GET"
+      url: /test_0/redirect-to?url=http://127.0.0.1:{httpbin_port}/cache/3
+      headers:
+        fields:
+          - [ uuid, 0-1-0 ]
+          - [ x-debug, x-cache ]
+
+    proxy-response:
+      status: 200
+      headers:
+        fields:
+        - [ x-cache, {{value: "miss", as: equal }} ]
+
+  - client-request:
+      method: "GET"
+      url: /test_0/redirect-to?url=http://127.0.0.1:{httpbin_port}/cache/3
+      headers:
+        fields:
+          - [ uuid, 0-1-1 ]
+          - [ x-debug, x-cache ]
+
+    proxy-response:
+      status: 200
+      headers:
+        fields:
+        - [ x-cache, {{value: "miss", as: equal }} ]
+
+
+  - client-request:
+      method: "GET"
+      url: /test_0/redirect-to?url=http://127.0.0.1:{httpbin_port}/cache/3
+      headers:
+        fields:
+          - [ uuid, 0-1-2 ]
+          - [ x-debug, x-cache ]
+
+    proxy-response:
+      status: 200
+      headers:
+        fields:
+        - [ x-cache, {{value: "hit-fresh", as: equal }} ]
+
+  #
+  # test case 1 : following redirect with cachekey plugin
+  #
+  - client-request:
+      method: "GET"
+      url: /test_1/redirect-to?url=http://127.0.0.1:{httpbin_port}/cache/4
+      headers:
+        fields:
+          - [ uuid, 1-0 ]
+          - [ x-debug, x-cache ]
+
+    proxy-response:
+      status: 200
+      headers:
+        fields:
+        - [ x-cache, {{value: "miss", as: equal }} ]
+
+  - client-request:
+      method: "GET"
+      url: /test_1/redirect-to?url=http://127.0.0.1:{httpbin_port}/cache/4
+      headers:
+        fields:
+          - [ uuid, 1-1 ]
+          - [ x-debug, x-cache ]
+
+    proxy-response:
+      status: 200
+      headers:
+        fields:
+        - [ x-cache, {{value: "miss", as: equal }} ]
+
+
+  - client-request:
+      method: "GET"
+      url: /test_1/redirect-to?url=http://127.0.0.1:{httpbin_port}/cache/4
+      headers:
+        fields:
+          - [ uuid, 1-2 ]
+          - [ x-debug, x-cache ]
+
+    proxy-response:
+      status: 200
+      headers:
+        fields:
+        - [ x-cache, {{value: "hit-fresh", as: equal }} ]

Reply via email to