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 468e76405a redo_cache_lookup: move to examples; fix `fallback`
lifetime (#13209)
468e76405a is described below
commit 468e76405a932efa55332a9ff70745e0a04c3b35
Author: Brian Neradt <[email protected]>
AuthorDate: Tue Jun 23 12:57:58 2026 -0500
redo_cache_lookup: move to examples; fix `fallback` lifetime (#13209)
The redo_cache_lookup plugin kept the fallback URL as a pointer into
the plugin.config argv storage. That storage can be released after
plugin initialization, leaving cache-lookup-complete callbacks to
dereference stale memory.
This copies the parsed fallback URL into plugin-owned storage and
passes its owned bytes to TSHttpTxnRedoCacheLookup.
Also, while investigating this, it looks like this plugin was made
simply to demonstrate the use of TSHttpTxnRedoCacheLookup rather than
being a production-useful plugin. The initial commit says as much and
there is no customer-facing documentation for this plugin. As such, I'm
moving this to the examples plugin.
---
cmake/ExperimentalPlugins.cmake | 1 -
example/plugins/c-api/CMakeLists.txt | 8 ++
example/plugins/c-api/redo_cache_lookup/readme.txt | 13 +++
.../c-api/redo_cache_lookup/redo_cache_lookup.cc | 91 ++++++++++++++++
.../redo_cache_lookup/redo_cache_lookup_config.h | 78 ++++++++++++++
.../unit_tests/test_redo_cache_lookup_config.cc | 66 ++++++++++++
plugins/experimental/CMakeLists.txt | 3 -
.../experimental/redo_cache_lookup/CMakeLists.txt | 21 ----
plugins/experimental/redo_cache_lookup/README.md | 11 --
.../redo_cache_lookup/redo_cache_lookup.cc | 115 ---------------------
10 files changed, 256 insertions(+), 151 deletions(-)
diff --git a/cmake/ExperimentalPlugins.cmake b/cmake/ExperimentalPlugins.cmake
index 5e73ffa5ec..4aff4543ab 100644
--- a/cmake/ExperimentalPlugins.cmake
+++ b/cmake/ExperimentalPlugins.cmake
@@ -83,7 +83,6 @@ auto_option(
)
auto_option(RATE_LIMIT FEATURE_VAR BUILD_RATE_LIMIT DEFAULT ${_DEFAULT})
auto_option(REALIP FEATURE_VAR BUILD_REALIP DEFAULT ${_DEFAULT})
-auto_option(REDO_CACHE_LOOKUP FEATURE_VAR BUILD_REDO_CACHE_LOOKUP DEFAULT
${_DEFAULT})
auto_option(SSLHEADERS FEATURE_VAR BUILD_SSLHEADERS DEFAULT ${_DEFAULT})
auto_option(STALE_RESPONSE FEATURE_VAR BUILD_STALE_RESPONSE DEFAULT
${_DEFAULT})
auto_option(
diff --git a/example/plugins/c-api/CMakeLists.txt
b/example/plugins/c-api/CMakeLists.txt
index 65594cd391..ea40f39cea 100644
--- a/example/plugins/c-api/CMakeLists.txt
+++ b/example/plugins/c-api/CMakeLists.txt
@@ -24,6 +24,7 @@ add_atsplugin(secure_link ./secure_link/secure_link.cc)
target_link_libraries(secure_link PRIVATE OpenSSL::SSL)
add_atsplugin(remap ./remap/remap.cc)
add_atsplugin(redirect_1 ./redirect_1/redirect_1.cc)
+add_atsplugin(redo_cache_lookup ./redo_cache_lookup/redo_cache_lookup.cc)
add_atsplugin(query_remap ./query_remap/query_remap.cc)
add_atsplugin(thread_pool ./thread_pool/psi.cc ./thread_pool/thread.cc)
add_atsplugin(bnull_transform ./bnull_transform/bnull_transform.cc)
@@ -66,3 +67,10 @@ add_atsplugin(protocol_stack
./protocol_stack/protocol_stack.cc)
add_atsplugin(client_context_dump ./client_context_dump/client_context_dump.cc)
target_link_libraries(client_context_dump PRIVATE OpenSSL::SSL
libswoc::libswoc)
add_atsplugin(custom_logfield ./custom_logfield/custom_logfield.cc)
+
+if(BUILD_TESTING)
+ add_executable(test_redo_cache_lookup
./redo_cache_lookup/unit_tests/test_redo_cache_lookup_config.cc)
+ target_include_directories(test_redo_cache_lookup PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/redo_cache_lookup)
+ target_link_libraries(test_redo_cache_lookup PRIVATE Catch2::Catch2WithMain)
+ add_catch2_test(NAME test_redo_cache_lookup COMMAND test_redo_cache_lookup)
+endif()
diff --git a/example/plugins/c-api/redo_cache_lookup/readme.txt
b/example/plugins/c-api/redo_cache_lookup/readme.txt
new file mode 100644
index 0000000000..9f3008400f
--- /dev/null
+++ b/example/plugins/c-api/redo_cache_lookup/readme.txt
@@ -0,0 +1,13 @@
+# Redo Cache Lookup Example Plugin
+
+This plugin shows how to use the `TSHttpTxnRedoCacheLookup` C API. It
+checks cache lookup results and asks ATS to retry the lookup with a fallback
+URL when the original lookup misses or is skipped.
+
+## Configuration
+
+Add this plugin to `plugin.config` with the `--fallback` option:
+
+```
+redo_cache_lookup.so --fallback http://example.com/fallback_url
+```
diff --git a/example/plugins/c-api/redo_cache_lookup/redo_cache_lookup.cc
b/example/plugins/c-api/redo_cache_lookup/redo_cache_lookup.cc
new file mode 100644
index 0000000000..c370fae0e2
--- /dev/null
+++ b/example/plugins/c-api/redo_cache_lookup/redo_cache_lookup.cc
@@ -0,0 +1,91 @@
+/** @file
+
+ An example plugin to redo cache lookups with a fallback URL.
+
+ @section license License
+
+ 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.
+ */
+
+#include <string>
+#include <string_view>
+
+#include "ts/ts.h"
+#include "redo_cache_lookup_config.h"
+
+#define PLUGIN_NAME "redo_cache_lookup"
+
+namespace
+{
+DbgCtl dbg_ctl{PLUGIN_NAME};
+
+struct RedoCacheLookupConfig {
+ RedoCacheLookupConfig(std::string_view fallback) : fallback(fallback) {}
+
+ std::string fallback;
+};
+
+int
+handle_cache_lookup_complete(TSCont contp, TSEvent event, void *edata)
+{
+ if (event != TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE) {
+ return 0;
+ }
+
+ TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
+ auto *config = static_cast<RedoCacheLookupConfig
*>(TSContDataGet(contp));
+ int status = TS_CACHE_LOOKUP_MISS;
+
+ if (TSHttpTxnCacheLookupStatusGet(txnp, &status) != TS_SUCCESS || status ==
TS_CACHE_LOOKUP_MISS ||
+ status == TS_CACHE_LOOKUP_SKIPPED) {
+ Dbg(dbg_ctl, "rewinding to check for fallback url: %s",
config->fallback.c_str());
+ TSHttpTxnRedoCacheLookup(txnp, config->fallback.c_str(),
static_cast<int>(config->fallback.size()));
+ }
+
+ TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+ return 0;
+}
+} // namespace
+
+void
+TSPluginInit(int argc, const char *argv[])
+{
+ TSPluginRegistrationInfo info;
+
+ Dbg(dbg_ctl, "Init");
+ info.plugin_name = PLUGIN_NAME;
+ info.vendor_name = "Apache Software Foundation";
+ info.support_email = "[email protected]";
+
+ if (TSPluginRegister(&info) != TS_SUCCESS) {
+ TSError("[%s] Plugin registration failed", PLUGIN_NAME);
+ return;
+ }
+
+ auto fallback = redo_cache_lookup::parse_fallback_url(argc, argv);
+
+ if (!fallback) {
+ Dbg(dbg_ctl, "Missing fallback option.");
+ TSError("[%s] Missing fallback option", PLUGIN_NAME);
+ return;
+ }
+ Dbg(dbg_ctl, "Initialized with fallback: %s", fallback->c_str());
+
+ TSCont contp = TSContCreate(handle_cache_lookup_complete, nullptr);
+ TSContDataSet(contp, new RedoCacheLookupConfig(*fallback));
+ TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, contp);
+}
diff --git a/example/plugins/c-api/redo_cache_lookup/redo_cache_lookup_config.h
b/example/plugins/c-api/redo_cache_lookup/redo_cache_lookup_config.h
new file mode 100644
index 0000000000..8158e4aec0
--- /dev/null
+++ b/example/plugins/c-api/redo_cache_lookup/redo_cache_lookup_config.h
@@ -0,0 +1,78 @@
+/** @file
+
+ Configuration helpers for the redo_cache_lookup plugin.
+
+ @section license License
+
+ 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.
+ */
+
+#pragma once
+
+#include <getopt.h>
+#include <optional>
+#include <string>
+
+namespace redo_cache_lookup
+{
+/** Parse the configured fallback URL from plugin arguments.
+ *
+ * @param[in] argc The number of plugin argument entries in @a argv.
+ * @param[in] argv The plugin arguments supplied from @c plugin.config.
+ * @return The configured fallback URL, or @c std::nullopt if no fallback URL
+ * is configured.
+ */
+inline std::optional<std::string>
+parse_fallback_url(int argc, const char *argv[])
+{
+ std::optional<std::string> fallback;
+
+ static const struct option longopts[] = {
+ {"fallback", required_argument, nullptr, 'f'},
+ {nullptr, 0, nullptr, 0 },
+ };
+
+#if (!defined(kfreebsd) && defined(freebsd)) || defined(darwin)
+ optreset = 1;
+#endif
+#if defined(__GLIBC__)
+ optind = 0;
+#else
+ optind = 1;
+#endif
+ opterr = 0;
+ optarg = nullptr;
+
+ int opt = 0;
+
+ while (opt >= 0) {
+ opt = getopt_long(argc, const_cast<char *const *>(argv), "f:", longopts,
nullptr);
+ switch (opt) {
+ case 'f':
+ fallback = optarg;
+ break;
+ case -1:
+ case '?':
+ break;
+ default:
+ return std::nullopt;
+ }
+ }
+
+ return fallback;
+}
+} // namespace redo_cache_lookup
diff --git
a/example/plugins/c-api/redo_cache_lookup/unit_tests/test_redo_cache_lookup_config.cc
b/example/plugins/c-api/redo_cache_lookup/unit_tests/test_redo_cache_lookup_config.cc
new file mode 100644
index 0000000000..905af6dfe6
--- /dev/null
+++
b/example/plugins/c-api/redo_cache_lookup/unit_tests/test_redo_cache_lookup_config.cc
@@ -0,0 +1,66 @@
+/** @file
+
+ Tests for redo_cache_lookup plugin configuration parsing.
+
+ @section license License
+
+ 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.
+ */
+
+#include <catch2/catch_test_macros.hpp>
+
+#include <cstring>
+
+#include "redo_cache_lookup_config.h"
+
+TEST_CASE("redo_cache_lookup fallback option is copied", "[redo_cache_lookup]")
+{
+ char plugin_name[] = "redo_cache_lookup.so";
+ char fallback_opt[] = "--fallback";
+ char fallback_url[] = "http://example.test/fallback";
+ const char *argv[] = {plugin_name, fallback_opt, fallback_url};
+
+ auto parsed = redo_cache_lookup::parse_fallback_url(3, argv);
+
+ REQUIRE(parsed.has_value());
+
+ std::memset(fallback_url, 'x', sizeof(fallback_url) - 1);
+
+ REQUIRE(*parsed == "http://example.test/fallback");
+}
+
+TEST_CASE("redo_cache_lookup fallback option accepts short form",
"[redo_cache_lookup]")
+{
+ char plugin_name[] = "redo_cache_lookup.so";
+ char fallback_opt[] = "-f";
+ char fallback_url[] = "http://example.test/short";
+ const char *argv[] = {plugin_name, fallback_opt, fallback_url};
+
+ auto parsed = redo_cache_lookup::parse_fallback_url(3, argv);
+
+ REQUIRE(parsed == "http://example.test/short");
+}
+
+TEST_CASE("redo_cache_lookup fallback option is required",
"[redo_cache_lookup]")
+{
+ char plugin_name[] = "redo_cache_lookup.so";
+ const char *argv[] = {plugin_name};
+
+ auto parsed = redo_cache_lookup::parse_fallback_url(1, argv);
+
+ REQUIRE_FALSE(parsed.has_value());
+}
diff --git a/plugins/experimental/CMakeLists.txt
b/plugins/experimental/CMakeLists.txt
index fe7897c585..bd8cf64e0f 100644
--- a/plugins/experimental/CMakeLists.txt
+++ b/plugins/experimental/CMakeLists.txt
@@ -98,9 +98,6 @@ endif()
if(BUILD_REALIP)
add_subdirectory(realip)
endif()
-if(BUILD_REDO_CACHE_LOOKUP)
- add_subdirectory(redo_cache_lookup)
-endif()
if(BUILD_SSLHEADERS)
add_subdirectory(sslheaders)
endif()
diff --git a/plugins/experimental/redo_cache_lookup/CMakeLists.txt
b/plugins/experimental/redo_cache_lookup/CMakeLists.txt
deleted file mode 100644
index 1b6c41d47b..0000000000
--- a/plugins/experimental/redo_cache_lookup/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-#######################
-#
-# 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.
-#
-#######################
-
-add_atsplugin(redo_cache_lookup redo_cache_lookup.cc)
-
-target_link_libraries(redo_cache_lookup PRIVATE ts::tscppapi)
-verify_global_plugin(redo_cache_lookup)
diff --git a/plugins/experimental/redo_cache_lookup/README.md
b/plugins/experimental/redo_cache_lookup/README.md
deleted file mode 100644
index 7ad5ddae36..0000000000
--- a/plugins/experimental/redo_cache_lookup/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Redo Cache Lookup Plugin
-
-This plugin shows how to use the experimental `TSHttpTxnRedoCacheLookup` api.
It works by checking the cache for a fallback url if the cache lookup failed
for any given url.
-
-## Configuration
-
-Add this plugin to `plugin.config` with the `--fallback` option:
-
-```
-redo_cache_lookup.so --fallback http://example.com/fallback_url
-```
\ No newline at end of file
diff --git a/plugins/experimental/redo_cache_lookup/redo_cache_lookup.cc
b/plugins/experimental/redo_cache_lookup/redo_cache_lookup.cc
deleted file mode 100644
index 6e917c700a..0000000000
--- a/plugins/experimental/redo_cache_lookup/redo_cache_lookup.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-/** @file
-
- A plugin to redo cache lookups with a fallback if cache lookups fail for
specific urls.
-
- @section license License
-
- 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.
- */
-
-#include <iostream>
-#include <regex>
-#include <cstring>
-#include <set>
-#include <sstream>
-#include <getopt.h>
-
-#include <ts/ts.h>
-#include "tscpp/api/GlobalPlugin.h"
-#include "tscpp/api/utils.h"
-
-#define PLUGIN_NAME "redo_cache_lookup"
-
-using namespace atscppapi;
-
-namespace
-{
-GlobalPlugin *plugin;
-
-DbgCtl dbg_ctl{PLUGIN_NAME};
-} // namespace
-
-class RedoCacheLookupPlugin : public GlobalPlugin
-{
-public:
- RedoCacheLookupPlugin(const char *fallback) : fallback(fallback)
- {
- Dbg(dbg_ctl, "registering transaction hooks");
- RedoCacheLookupPlugin::registerHook(HOOK_CACHE_LOOKUP_COMPLETE);
- }
-
- void
- handleReadCacheLookupComplete(Transaction &transaction) override
- {
- Transaction::CacheStatus status = transaction.getCacheStatus();
-
- if (status == Transaction::CacheStatus::CACHE_LOOKUP_NONE || status ==
Transaction::CacheStatus::CACHE_LOOKUP_SKIPED ||
- status == Transaction::CacheStatus::CACHE_LOOKUP_MISS) {
- Dbg(dbg_ctl, "rewinding to check for fallback url: %s", fallback);
- TSHttpTxn txnp = static_cast<TSHttpTxn>(transaction.getAtsHandle());
- TSHttpTxnRedoCacheLookup(txnp, fallback, strlen(fallback));
- }
-
- transaction.resume();
- }
-
-private:
- const char *fallback;
-};
-
-void
-TSPluginInit(int argc, const char *argv[])
-{
- Dbg(dbg_ctl, "Init");
- if (!RegisterGlobalPlugin("RedoCacheLookupPlugin", PLUGIN_NAME,
"[email protected]")) {
- return;
- }
-
- const char *fallback = nullptr;
-
- // Read options from plugin.config
- static const struct option longopts[] = {
- {"fallback", required_argument, nullptr, 'f'}
- };
-
- int opt = 0;
-
- while (opt >= 0) {
- opt = getopt_long(argc, const_cast<char *const *>(argv), "f:", longopts,
nullptr);
- switch (opt) {
- case 'f':
- fallback = optarg;
- break;
- case -1:
- case '?':
- break;
- default:
- Dbg(dbg_ctl, "Unexpected option: %i", opt);
- TSError("[%s] Unexpected options error.", PLUGIN_NAME);
- return;
- }
- }
-
- if (nullptr == fallback) {
- Dbg(dbg_ctl, "Missing fallback option.");
- TSError("[%s] Missing fallback option", PLUGIN_NAME);
- return;
- }
- Dbg(dbg_ctl, "Initialized with fallback: %s", fallback);
-
- plugin = new RedoCacheLookupPlugin(fallback);
-}