This is an automated email from the ASF dual-hosted git repository.
mlibbey 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 03652e4928 prefetch: admit --fetch-query requests only when the key is
present (#13370)
03652e4928 is described below
commit 03652e4928a0c18cc7256e1dfaed7e7001abf5db
Author: Miles Libbey <[email protected]>
AuthorDate: Sat Jul 18 16:45:30 2026 -0700
prefetch: admit --fetch-query requests only when the key is present (#13370)
With --fetch-query configured, the front-end/first-pass gate set
handleFetch=true whenever the query key was *configured*, not when the
request carried it. So every request whose path matched no
fetch-path-pattern was admitted anyway, ran the pattern replace, failed,
and logged ERROR "failed to process the pattern" -- while scheduling no
prefetch at all (BgFetch runs only on the success path).
Admit only when the request's query actually contains the key, matched
as a "<key>=" parameter rather than a substring (which could hit another
parameter's name or value). The same parameter test is now used by the
hasValidQuery branch selector and the query-branch loop as well.
---
plugins/prefetch/plugin.cc | 37 +++++++++++++++++++++++++++++++------
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/plugins/prefetch/plugin.cc b/plugins/prefetch/plugin.cc
index b935e7928d..a472bea0d5 100644
--- a/plugins/prefetch/plugin.cc
+++ b/plugins/prefetch/plugin.cc
@@ -348,6 +348,31 @@ getPristineUrlQuery(TSHttpTxn txnp)
return pristineQuery;
}
+/**
+ * @brief Whether a single query parameter is the configured "<key>=..."
parameter.
+ */
+static bool
+isQueryKeyParam(const String ¶m, const String &key)
+{
+ return param.size() > key.size() && param.compare(0, key.size(), key) == 0
&& param[key.size()] == '=';
+}
+
+/**
+ * @brief Whether the query string contains the configured "<key>=..."
parameter.
+ */
+static bool
+hasQueryKeyParam(const String &query, const String &key)
+{
+ std::istringstream qs(query);
+ String param;
+ while (getline(qs, param, '&')) {
+ if (isQueryKeyParam(param, key)) {
+ return true;
+ }
+ }
+ return false;
+}
+
static constexpr StringView CmcdHeader{"Cmcd-Request"};
static constexpr StringView CmcdNorFieldPrefix{"nor="};
static constexpr StringView CmcdNrrFieldPrefix{"nrr="};
@@ -590,9 +615,9 @@ contHandleFetch(const TSCont contp, TSEvent event, void
*edata)
const String currentQuery = getPristineUrlQuery(txnp);
bool hasValidQuery = false;
- // If there is a --fetch-query defined in the config, and that string is
found in the querystring, assume it is
- // valid, and prefer the --fetch-query over the --fetch-path-pattern(s).
- if (!config.getQueryKeyName().empty() &&
currentQuery.find(config.getQueryKeyName()) != String::npos) {
+ // If there is a --fetch-query defined in the config, and that parameter
is present in the querystring, assume it
+ // is valid, and prefer the --fetch-query over the
--fetch-path-pattern(s).
+ if (!config.getQueryKeyName().empty() && hasQueryKeyParam(currentQuery,
config.getQueryKeyName())) {
PrefetchDebug("Setting hasValidQuery to true");
hasValidQuery = true;
}
@@ -663,7 +688,7 @@ contHandleFetch(const TSCont contp, TSEvent event, void
*edata)
String param;
while (getline(cStringStream, param, '&')) {
- if (param.find(config.getQueryKeyName()) != 0) {
+ if (!isQueryKeyParam(param, config.getQueryKeyName())) {
continue;
}
if (config.getFetchCount() < done++) {
@@ -851,8 +876,8 @@ TSRemapDoRemap(void *instance, TSHttpTxn txnp,
TSRemapRequestInfo *rri)
PrefetchDebug("failed to get path to (pre)match");
}
- String queryKey = config.getQueryKeyName();
- if (!queryKey.empty()) {
+ const String &queryKey = config.getQueryKeyName();
+ if (!handleFetch && !queryKey.empty() &&
hasQueryKeyParam(getPristineUrlQuery(txnp), queryKey)) {
PrefetchDebug("handling for query-key: %s", queryKey.c_str());
handleFetch = true;
}