Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions doc/admin-guide/plugins/cachekey.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,29 @@ Cache key structure and related plugin parameters

::

Optional components | ┌─────────────────┬─────────────────┬──────────────────────┐
Optional components | ┌─────────────────┬────────────── ───┬──────────────────────┐
(included in this order) | │ --static-prefix | --capture-prefix │ --capture-prefix-uri │
| ├─────────────────┴──────────────────┴──────────────────────┤
Default values if no | │ /host/port |
Default values if no | │ /host/port or scheme://host:port (see the table below) |
optional components | └───────────────────────────────────────────────────────────┘
configured |

┌────────────────────┬─────────────────────────┬──────────────────────┐
│ --canonical-prefix | default value if no │ input used for │
│ | prefix parameters used │ --capture-prefix │
├────────────────────┴─────────────────────────┴──────────────────────┤
│ fasle | /host/port | host:port |
├────────────────────┴─────────────────────────┴──────────────────────┤
│ true | scheme://host:port | scheme://host:port |
└──────────────────────────────────────────────┴──────────────────────┘


* ``--static-prefix=<value>`` (default: empty string) - if specified and not an empty string the ``<value>`` will be added to the cache key.
* ``--capture-prefix=<capture_definition>`` (default: empty string) - if specified and not empty then strings are captured from ``host:port`` based on the ``<capture_definition>`` and are added to the cache key.
* ``--capture-prefix=<capture_definition>`` (default: empty string) - if specified and not empty then strings are captured based on the value of ``--canonical-prefix`` parameter (see the table above) and ``<capture_definition>`` and are added to the cache key.
* ``--capture-prefix-uri=<capture_definition>`` (default: empty string) - if specified and not empty then strings are captured from the entire URI based on the ``<capture_definition>`` and are added to the cache key.
* If any of the "Prefix" related plugin parameters are used together in the plugin configuration they are added to the cache key in the order shown in the diagram.
* ``--remove-prefix=<true|false|yes|no|0|1`` (default: false) - if specified the prefix elements (host, port) are not processed nor appended to the cachekey. All prefix related plugin parameters are ignored if this parameter is ``true``, ``yes`` or ``1``.


* ``--remove-prefix=true|false|yes|no|0|1`` (default: false) - if specified the prefix elements (host, port) are not processed nor appended to the cachekey. All prefix related plugin parameters are ignored if this parameter is ``true``, ``yes`` or ``1``.
* ``--canonical-prefix=true|false|yes|no|0|1`` (default: false) - impacts the input of regex operation when ``--capture-prefix`` is used and the default value if no prefix parameters are used (see the table above).

"User-Agent" section
^^^^^^^^^^^^^^^^^^^^
Expand Down
90 changes: 67 additions & 23 deletions plugins/cachekey/cachekey.cc
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,51 @@ getUri(TSMBuffer buf, TSMLoc url)
return uri;
}

static String
getCanonicalUrl(TSMBuffer buf, TSMLoc url, bool canonicalPrefix, bool provideDefaultKey)
{
String canonicalUrl;

String scheme;
int schemeLen;
const char *schemePtr = TSUrlSchemeGet(buf, url, &schemeLen);
if (nullptr != schemePtr && 0 != schemeLen) {
scheme.assign(schemePtr, schemeLen);
} else {
CacheKeyError("failed to get scheme");
return canonicalUrl;
}

String host;
int hostLen;
const char *hostPtr = TSUrlHostGet(buf, url, &hostLen);
if (nullptr != hostPtr && 0 != hostLen) {
host.assign(hostPtr, hostLen);
} else {
CacheKeyError("failed to get host");
return canonicalUrl;
}

String port;
int portInt = TSUrlPortGet(buf, url);
::append(port, portInt);

if (canonicalPrefix) {
/* return the same for both regex input or default key, results in 'scheme://host:port' */
canonicalUrl.assign(scheme).append("://").append(host).append(":").append(port);
} else {
if (provideDefaultKey) {
/* return the key default - results in '/host/port' */
canonicalUrl.assign("/").append(host).append("/").append(port);
} else {
/* return regex input string - results in 'host:port' (use-case kept for compatibility reasons) */
canonicalUrl.assign(host).append(":").append(port);
}
}

return canonicalUrl;
}

/**
* @brief Constructor setting up the cache key prefix, initializing request info.
* @param txn transaction handle.
Expand Down Expand Up @@ -289,6 +334,16 @@ CacheKey::append(const String &s)
::appendEncoded(_key, s.data(), s.size());
}

void
CacheKey::append(const String &s, bool useSeparator)
{
if (useSeparator) {
append(s);
} else {
_key.append(s);
}
}

/**
* @brief Append null-terminated C-style string to the key.
* @param s null-terminated C-style string.
Expand Down Expand Up @@ -319,42 +374,31 @@ CacheKey::append(const char *s, unsigned n)
* @param prefix if not empty string will append the static prefix to the cache key.
* @param prefixCapture if not empty will append regex capture/replacement from the host:port.
* @param prefixCaptureUri if not empty will append regex capture/replacement from the whole URI.
* @param canonicalPrefix false - use 'host:port' as starting point of all transformations, true - use 'scheme://host:port'
* @note if both prefix and pattern are not empty prefix will be added first, followed by the results from pattern.
*/
void
CacheKey::appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern &prefixCaptureUri)
CacheKey::appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern &prefixCaptureUri, bool canonicalPrefix)
{
// "true" would mean that the plugin config meant to override the default prefix (host:port).
// "true" would mean that the plugin config meant to override the default prefix, "false" means use default.
bool customPrefix = false;
String host;
int port = 0;

/* For all the following operations if a canonical prefix is required then appned to the key with no separator
* to leave the door open for potential valid host name formed in the final resulting cache key. */

if (!prefix.empty()) {
customPrefix = true;
append(prefix);
append(prefix, /* useSeparator */ !canonicalPrefix);
CacheKeyDebug("added static prefix, key: '%s'", _key.c_str());
}

int hostLen;
const char *hostPtr = TSUrlHostGet(_buf, _url, &hostLen);
if (nullptr != hostPtr && 0 != hostLen) {
host.assign(hostPtr, hostLen);
} else {
CacheKeyError("failed to get host");
}
port = TSUrlPortGet(_buf, _url);

if (!prefixCapture.empty()) {
customPrefix = true;

String hostAndPort;
hostAndPort.append(host).append(":");
::append(hostAndPort, port);

StringVector captures;
if (prefixCapture.process(hostAndPort, captures)) {
if (prefixCapture.process(getCanonicalUrl(_buf, _url, canonicalPrefix, /* provideDefaultKey */ false), captures)) {
for (auto &capture : captures) {
append(capture);
append(capture, /* useSeparator */ !canonicalPrefix);
}
CacheKeyDebug("added host:port capture prefix, key: '%s'", _key.c_str());
}
Expand All @@ -368,16 +412,16 @@ CacheKey::appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern &pr
StringVector captures;
if (prefixCaptureUri.process(uri, captures)) {
for (auto &capture : captures) {
append(capture);
append(capture, /* useSeparator */ !canonicalPrefix);
}
CacheKeyDebug("added URI capture prefix, key: '%s'", _key.c_str());
}
}
}

if (!customPrefix) {
append(host);
append(port);
/* nothing was customized => default prefix */
append(getCanonicalUrl(_buf, _url, canonicalPrefix, /* provideDefaultKey */ true), /* useSeparator */ false);
CacheKeyDebug("added default prefix, key: '%s'", _key.c_str());
}
}
Expand Down
3 changes: 2 additions & 1 deletion plugins/cachekey/cachekey.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ class CacheKey

void append(unsigned number);
void append(const String &);
void append(const String &s, bool useSeparator);
void append(const char *s);
void append(const char *n, unsigned s);
void appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern &prefixCaptureUri);
void appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern &prefixCaptureUri, bool canonicalPrefix);
void appendPath(Pattern &pathCapture, Pattern &pathCaptureUri);
void appendHeaders(const ConfigHeaders &config);
void appendQuery(const ConfigQuery &config);
Expand Down
11 changes: 11 additions & 0 deletions plugins/cachekey/configs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ Configs::init(int argc, const char *argv[], bool perRemapConfig)
{const_cast<char *>("separator"), optional_argument, nullptr, 's'},
{const_cast<char *>("uri-type"), optional_argument, nullptr, 't'},
{const_cast<char *>("capture-header"), optional_argument, nullptr, 'u'},
{const_cast<char *>("canonical-prefix"), optional_argument, nullptr, 'v'},
/* reserve 'z' for 'config' files */
{nullptr, 0, nullptr, 0},
};

Expand Down Expand Up @@ -504,6 +506,9 @@ Configs::init(int argc, const char *argv[], bool perRemapConfig)
case 'u': /* capture-header */
_headers.addCapture(optarg);
break;
case 'v': /* canonical-prefix */
_canonicalPrefix = isTrue(optarg);
break;
}
}

Expand Down Expand Up @@ -535,6 +540,12 @@ Configs::pathToBeRemoved()
return _pathToBeRemoved;
}

bool
Configs::canonicalPrefix()
{
return _canonicalPrefix;
}

void
Configs::setSeparator(const char *arg)
{
Expand Down
6 changes: 6 additions & 0 deletions plugins/cachekey/configs.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ class Configs
*/
bool pathToBeRemoved();

/**
* @brief keep URI scheme and authority elements.
*/
bool canonicalPrefix();

/**
* @brief set the cache key elements separator string.
*/
Expand Down Expand Up @@ -205,6 +210,7 @@ class Configs

bool _prefixToBeRemoved = false; /**< @brief instructs the prefix (i.e. host:port) not to added to the cache key */
bool _pathToBeRemoved = false; /**< @brief instructs the path not to added to the cache key */
bool _canonicalPrefix = false; /**< @brief keep the URI scheme and authority element used as input to transforming into key */
String _separator = "/"; /**< @brief a separator used to separate the cache key elements extracted from the URI */
CacheKeyUriType _uriType = REMAP; /**< @brief shows which URI the cache key will be based on */
};
2 changes: 1 addition & 1 deletion plugins/cachekey/plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ setCacheKey(TSHttpTxn txn, Configs *config, TSRemapRequestInfo *rri = nullptr)

/* Append custom prefix or the host:port */
if (!config->prefixToBeRemoved()) {
cachekey.appendPrefix(config->_prefix, config->_prefixCapture, config->_prefixCaptureUri);
cachekey.appendPrefix(config->_prefix, config->_prefixCapture, config->_prefixCaptureUri, config->canonicalPrefix());
}
/* Classify User-Agent and append the class name to the cache key if matched. */
cachekey.appendUaClass(config->_classifier);
Expand Down