This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch master
in repository https://git-dual.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 4546c09 TS-4183: cachekey: URI/prefix/path capture/replacement
4546c09 is described below
commit 4546c09915fec9ea0fb87dd692dde06ea92ad1bf
Author: Gancho Tenev <[email protected]>
AuthorDate: Thu Feb 11 16:29:41 2016 -0800
TS-4183: cachekey: URI/prefix/path capture/replacement
--capture-prefix-uri=regex
--capture-prefix-uri=/regex/replacement/
--capture-path-uri=regex
--capture-path-uri=/regex/replacement/
--capture-path=regex
--capture-path=/regex/replacement/
---
doc/admin-guide/plugins/cachekey.en.rst | 237 ++++++++++++++++-----
plugins/experimental/cachekey/cachekey.cc | 119 +++++++++--
plugins/experimental/cachekey/cachekey.h | 4 +-
plugins/experimental/cachekey/configs.cc | 49 +++--
plugins/experimental/cachekey/configs.h | 17 +-
plugins/experimental/cachekey/plugin.cc | 6 +-
.../experimental/cachekey/tests/test_cachekey.py | 99 ++++++++-
7 files changed, 428 insertions(+), 103 deletions(-)
diff --git a/doc/admin-guide/plugins/cachekey.en.rst
b/doc/admin-guide/plugins/cachekey.en.rst
index 51310d7..685a395 100644
--- a/doc/admin-guide/plugins/cachekey.en.rst
+++ b/doc/admin-guide/plugins/cachekey.en.rst
@@ -33,44 +33,134 @@ This plugin allows some common cache key manipulations
based on various HTTP req
* include headers or cookies by name
* capture values from the ``User-Agent`` header.
* classify request using ``User-Agent`` and a list of regular expressions
+* capture and replace strings from the URI and include them in the cache key
+* do more - please find more examples below.
-Plugin parameters
-=================
+Cache key structure and related plugin parameters
+=================================================
+
+::
+
+ hierarchical part
query
+
┌───────────────────────────────────┴────────────────────────────────────┐┌─────┴──────┐
+
┌─────────────┬──────────────┬──────────────┬──────────────┬─────────────┬─────────────┐
+ │ Prefix | User-Agent │ Headers │ Cookies │ Path │
Query │
+ │ section | section │ section │ section │ section │
section │
+ │ (default) | (optional) │ (optional) │ (optional) │ (default) │
(default) │
+
└─────────────┴──────────────┴──────────────┴──────────────┴─────────────┴─────────────┘
+
+* The cache key set by the cachekey plugin can be considered as devided into
several sections.
+* Every section is manupulated separately by the related plugin parameters
(more info in each section description below).
+* "User-Agent", "Headers" and "Cookies" sections are optional and will be
missing from the cache key if no related plugin parameters are used.
+* "Prefix", "Path" and "Query" sections always have default values even if no
related plugin parameters are used.
+* All cachekey plugin parameters are optional and if missing some of the cache
key sections will be missing (the optional sections) or their values will be
left to their defaults.
+
+"Prefix" section
+^^^^^^^^^^^^^^^^
+
+::
+
+ Optional components |
┌─────────────────┬──────────────────┬──────────────────────┐
+ (included in this order) | │ --static-prefix | --capture-prefix │
--capture-prefix-uri │
+ |
├─────────────────┴──────────────────┴──────────────────────┤
+ Default values if no | │ /host/port
|
+ optional components |
└───────────────────────────────────────────────────────────┘
+ configured |
+
+* ``--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-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.
-All parameters are optional, and if not used, their default values are as
mentioned below. Boolean values default to ``false`` and the rest default to an
empty list. Examples of each parameter's usage can be found below.
-* URI query parameters
- * If no query related plugin parameters are used, the query is included as
received from the UA in the cache key.
- * ``--exclude-params`` (default: empty list) - comma-separated list of
query params to be black-listed in the cache key. If the list is empty then no
black-list is applied (no query parameters will be excluded from the cache
key). The exclude list overrides the include list.
- * ``--include-params`` (default: empty list) - comma-separated list of
query params to be white-listed in the cache key. If the list is empty then no
white-list is applied (all query parameters will be included in the cache key).
- * ``--include-match-params`` (default: empty list) - regular expression
matching query parameter names which will be white-listed in the cache key.
- * ``--exclude-match-params`` (default: empty list) - regular expression
matching query parameter names which will be black-listed in the cache key.
- * ``--remove-all-params`` (boolean:``true|false``, ``0|1``, ``yes|no``,
default: ``false``) - if equals ``true`` then all query parameters are removed
(the whole query string) and all other URI query parameter related settings (if
used) will have no effect.
- * ``--sort-params`` (boolean:``true|false``, ``0|1``, ``yes|no``, default:
``false``) - if equals ``true`` then all query parameters are sorted in an
increasing case-sensitive order
-* HTTP headers
- * ``--include-headers`` (default: empty list) - comma separated list of
headers to be added to the cache key.
-* HTTP cookies
- * ``--include-cookies`` (default: empty list) - comma separated list of
cookies to be added to the cache key.
-
-* Host name, port and custom prefix
- * Host and port are added to the beginning of the cache key by default
unless a custom preffix by using ``--static-prefix`` or ``--capture-prefix``
plugin parameters is specified.
- * ``--static-prefix`` (default: empty string) - if specified and not an
empty string the value will be added to the beginning of the cache key.
- * ``--capture-prefix=<capture_definition>`` (default: empty string) - if
specified and not an empty string will capture strings from ``host:port`` based
on the ``<capture_definition>`` (see below) and add them to the beginning of
the cache key.
- * If ``--static-prefix`` and ``--capture-prefix`` are used together then
the value of ``--static-prefix`` is added first to the cache key, followed by
the ``--capture-prefix`` capturing/replacement results.
+"User-Agent" section
+^^^^^^^^^^^^^^^^^^^^
+
+::
+
+ Optional components | ┌────────────┬──────────────┐
+ (included in this order) | │ --ua-class | --ua-capture │
+ | ├────────────┴──────────────┤
+ Default values if no | │ (empty) |
+ optional components | └───────────────────────────┘
+ configured |
* ``User-Agent`` classification
* ``--ua-whitelist=<classname>:<filename>`` (default: empty string) -
loads a regex patterns list from a file ``<filename>``, the patterns are
matched against the ``User-Agent`` header and if matched ``<classname>`` is
added it to the key.
* ``--ua-blacklist=<classname>:<filename>`` (default: empty string) -
loads a regex patterns list from a file ``<filename>``, the patterns are
matched against the ``User-Agent`` header and if **not** matched
``<classname>`` is added it to the key.
-
+ * Multiple ``--ua-whitelist`` and ``--ua-blacklist`` can be used and the
result will be defined by their order in the plugin configuration.
* ``User-Agent`` regex capturing and replacement
- * ``--ua-capture=<capture_definition>`` (default: empty string) - if
specified and not an empty string will capture strings from ``User-Agent``
header based on ``<capture_definition>`` (see below) and will add them to the
cache key.
+ * ``--ua-capture=<capture_definition>`` (default: empty string) - if
specified and not empty then strings are captured from the ``User-Agent``
header based on ``<capture_definition>`` (see below) and are added to the cache
key.
+* If any ``User-Agent`` classigication and regex capturing and replacement
plugin parameters are used together they are added to the cache key in the
order shown in the diagram.
+
+"Headers" section
+^^^^^^^^^^^^^^^^^
+
+::
+
+ Optional components | ┌───────────────────┐
+ | │ --include-headers │
+ | ├───────────────────┤
+ Default values if no | │ (empty) |
+ optional components | └───────────────────┘
+ configured |
+
+* ``--include-headers`` (default: empty list) - comma separated list of
headers to be added to the cache key. The list of headers defined by
``--include-headers`` are always sorted before adding them to the cache key.
+
+"Cookies" section
+^^^^^^^^^^^^^^^^
+
+::
+
+ Optional components | ┌───────────────────┐
+ | │ --include-cookies │
+ | ├───────────────────┤
+ Default values if no | │ (empty) |
+ optional components | └───────────────────┘
+ configured |
+
+* ``--include-cookies`` (default: empty list) - comma separated list of
cookies to be added to the cache key. The list of cookies defined by
``--include-cookies`` are always sorted before adding them to the cache key.
+
+"Path" section
+^^^^^^^^^^^^^^
+
+::
+
+ Optional components | ┌────────────────────┬────────────────┐
+ (included in this order) | │ --path-capture-uri | --path-capture │
+ | ├────────────────────┴────────────────┤
+ Default values if no | │ URI path |
+ optional components | └─────────────────────────────────────┘
+ configured |
+
+* if no path related plugin parameters are used, the URI path string is
included in the cache key.
+* ``--capture-path=<capture_definition>`` (default: empty string) - if
specified and not empty then strings are captured from URI path based on the
``<capture_definition>`` and are added to the cache key.
+* ``--capture-path-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.
+
+"Query" section
+^^^^^^^^^^^^^^^
+
+* If no query related plugin parameters are used, the query string is included
in the cache key.
+* ``--exclude-params`` (default: empty list) - comma-separated list of query
params to be black-listed in the cache key. If the list is empty then no
black-list is applied (no query parameters will be excluded from the cache
key). The exclude list overrides the include list.
+* ``--include-params`` (default: empty list) - comma-separated list of query
params to be white-listed in the cache key. If the list is empty then no
white-list is applied (all query parameters will be included in the cache key).
+* ``--include-match-params`` (default: empty list) - regular expression
matching query parameter names which will be white-listed in the cache key.
+* ``--exclude-match-params`` (default: empty list) - regular expression
matching query parameter names which will be black-listed in the cache key.
+* ``--remove-all-params`` (boolean:``true|false``, ``0|1``, ``yes|no``,
default: ``false``) - if equals ``true`` then all query parameters are removed
(the whole query string) and all other URI query parameter related settings (if
used) will have no effect.
+* ``--sort-params`` (boolean:``true|false``, ``0|1``, ``yes|no``, default:
``false``) - if equals ``true`` then all query parameters are sorted in an
increasing case-sensitive order
+
+All parameters are optional, and if not used, their default values are as
mentioned below. Boolean values default to ``false`` and the rest default to an
empty list. Examples of each parameter's usage can be found below.
+
+
+<capture_definition>
+^^^^^^^^^^^^^^^^^^^^
* ``<capture_definition>`` can be in the following formats
* ``<regex>`` - ``<regex>`` defines regex capturing groups, up to 10
captured strings based on ``<regex>`` will be added to the cache key.
* ``/<regex>/<replacement>/`` - ``<regex>`` defines regex capturing
groups, ``<replacement>`` defines a pattern where the captured strings
referenced with ``$0`` ... ``$9`` will be substituted and the result will be
added to the cache key.
-Cache Key Structure
-===================
+
+Detailed examples and troubleshooting
+=====================================
::
@@ -84,21 +174,6 @@ Cache Key Structure
Cache Key | host:port or UA-class UA-captures headers cookies
path query
components | custom prefix replacement
-
-* With the current implementation the following cache key components are
always present in the cache key:
- * ``prefix or host:port`` - included at the beginning of the cache key. If
neither ``--static-prefix`` nor ``--capture-prefix`` are specified or are empty
strings then ``host:port`` from the request URI are used.
- * ``path`` - URI path included **as is** (but can be empty)
-* The rest of the cache key components are optional and their presence in the
cache key depends on the plugin configuration and the HTTP requests handled by
the plugin:
- * ``UA-class`` - a single class name, result of UA classification defined
by ``--ua-whitelist`` and ``--ua-blacklist`` parameters.
- * ``UA-captures`` - a result of the regex capture (and possibly
replacement) from the first ``User-Agent`` header.
- * ``headers`` - always sorted list of headers defined by
``--include-headers``
- * ``cookies`` - always sorted list of headers defined by
``--include-cookies``
- * ``query`` - the request URI query **as is** or a list of query
parameters proccessed by this plugin as configured.
-* The following URI components are ignored (not included in the cache key):
- * ``scheme:``
- * ``user:password@`` from the ``authority`` URI component
- * ``#fragment``
-
The following is an example of how the above sample keys were generated
(``Sample 1`` and ``Sample 2``).
Traffic server configuration ::
@@ -278,8 +353,9 @@ The following headers ``CookieA`` and ``CookieB`` will be
used when constructing
@plugin=cachekey.so @pparam=--include-headers=CookieA,CookieB
-Host name, port and static prefix
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Prefix (host, port, capture and replace from URI)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
Replacing host:port with a static cache key prefix
"""""""""""""""""""""""""""""""""""""""""""""""""""
If the plugin is used with the following plugin parameter in the remap rule. ::
@@ -288,22 +364,87 @@ If the plugin is used with the following plugin parameter
in the remap rule. ::
the cache key will be prefixed with ``/static_prefix`` instead of
``host:port`` when ``--static-prefix`` is not used.
-Capturing from the host:port and adding it to beginning of cache key prefix
-"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+Capturing from the host:port and adding it to the prefix section
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
If the plugin is used with the following plugin parameter in the remap rule. ::
- @plugin=cachekey.so @pparam=--capture-prefix=(test_prefix).*:([^\s\/$]*)
+ @plugin=cachekey.so \
+ @pparam=--capture-prefix=(test_prefix).*:([^\s\/$]*)
the cache key will be prefixed with ``/test_prefix/80`` instead of
``test_prefix_371.example.com:80`` when ``--capture-prefix`` is not used.
-Combining --static-prefix and --capture-prefix
-"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+Capturing from the entire URI and adding it to the prefix section
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
If the plugin is used with the following plugin parameter in the remap rule. ::
- @plugin=cachekey.so @pparam=--capture-prefix=(test_prefix).*:([^\s\/$]*)
@pparam=--static-prefix=static_prefix
+ @plugin=cachekey.so \
+ @pparam=--capture-prefix-uri=/(test_prefix).*:.*(object).*$/$1_$2/
+
+and if the request URI is the following ::
+
+ http://test_prefix_123.example.com/path/to/object?a=1&b=2&c=3
+
+the the cache key will be prefixed with ``/test_prefix_object`` instead of
``test_prefix_123.example.com:80`` when ``--capture-prefix-uri`` is not used.
+
+Combining prefix plugin parameters, i.e. --static-prefix and --capture-prefix
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+If the plugin is used with the following plugin parameters in the remap rule.
::
+
+ @plugin=cachekey.so \
+ @pparam=--capture-prefix=(test_prefix).*:([^\s\/$]*) \
+ @pparam=--static-prefix=static_prefix
the cache key will be prefixed with ``/static_prefix/test_prefix/80`` instead
of ``test_prefix_371.example.com:80`` when neither ``--capture-prefix`` nor
``--static-prefix`` are used.
+
+Path, capture and replace from the path or entire URI
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Capture and replace groups from path for the "Path" section
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+If the plugin is used with the following plugin parameter in the remap rule. ::
+
+ @plugin=cachekey.so \
+ @pparam=--capture-path=/.*(object).*/const_path_$1/
+
+and the request URI is the following ::
+
+ http://test_path_123.example.com/path/to/object?a=1&b=2&c=3
+
+then the cache key will have ``/const_path_object`` in the path section of the
cache key instead of ``/path/to/object`` when neither ``--capture-path`` nor
``--capture-path-uri`` are used.
+
+
+Capture and replace groups from whole URI for the "Path" section
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+If the plugin is used with the following plugin parameter in the remap rule. ::
+
+ @plugin=cachekey.so \
+ @pparam=--capture-path-uri=/(test_path).*(object).*/$1_$2/
+
+and the request URI is the following ::
+
+ http://test_path_123.example.com/path/to/object?a=1&b=2&c=3
+
+the the cache key will have ``/test_path_object`` in the path section of the
cache key instead of ``/path/to/object`` when neither ``--capture-path`` nor
``--capture-path-uri`` are used.
+
+
+Combining path plugin parameters --capture-path and --capture-path-uri
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+If the plugin is used with the following plugin parameters in the remap rule.
::
+
+ @plugin=cachekey.so \
+ @pparam=--capture-path=/.*(object).*/const_path_$1/ \
+ @pparam=--capture-path-uri=/(test_path).*(object).*/$1_$2/
+
+and the request URI is the following ::
+
+ http://test_path_123.example.com/path/to/object?a=1&b=2&c=3
+
+the the cache key will have ``/test_path_object/const_path_object`` in the
path section of the cache key instead of ``/path/to/object`` when neither
``--capture-path`` nor ``--capture-path-uri`` are used.
+
User-Agent capturing, replacement and classification
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Let us say we have a request with ``User-Agent`` header: ::
diff --git a/plugins/experimental/cachekey/cachekey.cc
b/plugins/experimental/cachekey/cachekey.cc
index c2246bd..5bb030e 100644
--- a/plugins/experimental/cachekey/cachekey.cc
+++ b/plugins/experimental/cachekey/cachekey.cc
@@ -229,17 +229,36 @@ CacheKey::append(const char *s, unsigned n)
::appendEncoded(_key, s, n);
}
+static String
+getUri(TSMBuffer buf, TSMLoc url)
+{
+ String uri;
+ int uriLen;
+ const char *uriPtr = TSUrlStringGet(buf, url, &uriLen);
+ if (NULL != uriPtr && 0 != uriLen) {
+ uri.assign(uriPtr, uriLen);
+ TSfree((void *)uriPtr);
+ } else {
+ CacheKeyError("failed to get URI");
+ }
+ return uri;
+}
+
/**
- * @brief Append a custom prefix or the host:port part of the URI to the cache
key.
+ * @brief Append to the cache key a custom prefix, capture from hots:port,
capture from URI or default to host:port part of the URI.
* @note This is the only cache key component from the key which is always
available.
- * @param prefix if not empty string the method will append the static prefix
to the cache key.
- * @param pattern if not empty the method will append the result of regex
capturing and/or replacement to the cache key.
+ * @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.
* @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 &pattern)
+CacheKey::appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern
&prefixCaptureUri)
{
+ // "true" would mean that the plugin config meant to override the default
prefix (host:port).
bool customPrefix = false;
+ String host;
+ int port = 0;
if (!prefix.empty()) {
customPrefix = true;
@@ -247,48 +266,106 @@ CacheKey::appendPrefix(const String &prefix, Pattern
&pattern)
CacheKeyDebug("added static prefix, key: '%s'", _key.c_str());
}
- int len;
- const char *ptr = TSUrlHostGet(_buf, _url, &len);
- int port = TSUrlPortGet(_buf, _url);
+ int hostLen;
+ const char *hostPtr = TSUrlHostGet(_buf, _url, &hostLen);
+ if (NULL != hostPtr && 0 != hostLen) {
+ host.assign(hostPtr, hostLen);
+ } else {
+ CacheKeyError("failed to get host");
+ }
+ port = TSUrlPortGet(_buf, _url);
- if (!pattern.empty()) {
+ if (!prefixCapture.empty()) {
customPrefix = true;
String hostAndPort;
- hostAndPort.append(ptr, len).append(":");
+ hostAndPort.append(host).append(":");
::append(hostAndPort, port);
StringVector captures;
- if (pattern.process(hostAndPort, captures)) {
+ if (prefixCapture.process(hostAndPort, captures)) {
for (StringVector::iterator it = captures.begin(); it != captures.end();
it++) {
append(*it);
}
- CacheKeyDebug("added capture prefix, key: '%s'", _key.c_str());
+ CacheKeyDebug("added host:port capture prefix, key: '%s'", _key.c_str());
+ }
+ }
+
+ if (!prefixCaptureUri.empty()) {
+ customPrefix = true;
+
+ String uri = getUri(_buf, _url);
+ if (!uri.empty()) {
+ StringVector captures;
+ if (prefixCaptureUri.process(uri, captures)) {
+ for (StringVector::iterator it = captures.begin(); it !=
captures.end(); it++) {
+ append(*it);
+ }
+ CacheKeyDebug("added URI capture prefix, key: '%s'", _key.c_str());
+ }
}
}
if (!customPrefix) {
- _key.append("/").append(ptr, len).append("/");
- ::append(_key, port);
+ append(host);
+ append(port);
CacheKeyDebug("added default prefix, key: '%s'", _key.c_str());
}
}
/**
- * @brief Appends the path from the URI to the cache key.
+ * @brief Appends to the cache key the path from the URI (default), regex
capture/replacement from the URI path,
+ * regex capture/replacement from URI as whole.
* @note A path is always defined for a URI, though the defined path may be
empty (zero length) (RFC 3986)
+ * @param pathCapture if not empty will append regex capture/replacement from
the URI path
+ * @param pathCaptureUri if not empty will append regex capture/replacement
from the URI as a whole
* @todo enhance, i.e. /<regex>/<replace>/
*/
void
-CacheKey::appendPath()
+CacheKey::appendPath(Pattern &pathCapture, Pattern &pathCaptureUri)
{
- const char *ptr;
- int len;
+ // "true" would mean that the plugin config meant to override the default
path.
+ bool customPath = false;
+ String path;
+
+ int pathLen;
+ const char *pathPtr = TSUrlPathGet(_buf, _url, &pathLen);
+ if (NULL != pathPtr && 0 != pathLen) {
+ path.assign(pathPtr, pathLen);
+ }
+
+ if (!pathCaptureUri.empty()) {
+ customPath = true;
+
+ String uri = getUri(_buf, _url);
+ if (!uri.empty()) {
+ StringVector captures;
+ if (pathCaptureUri.process(uri, captures)) {
+ for (StringVector::iterator it = captures.begin(); it !=
captures.end(); it++) {
+ append(*it);
+ }
+ CacheKeyDebug("added URI capture (path), key: '%s'", _key.c_str());
+ }
+ }
+ }
+
+ if (!pathCapture.empty()) {
+ customPath = true;
+
+ // If path is empty don't even try to capture/replace.
+ if (!path.empty()) {
+ StringVector captures;
+ if (pathCapture.process(path, captures)) {
+ for (StringVector::iterator it = captures.begin(); it !=
captures.end(); it++) {
+ append(*it);
+ }
+ CacheKeyDebug("added path capture, key: '%s'", _key.c_str());
+ }
+ }
+ }
- ptr = TSUrlPathGet(_buf, _url, &len);
- if (NULL != ptr && 0 != len) {
- _key.append("/");
- _key.append(ptr, len);
+ if (!customPath && !path.empty()) {
+ append(path);
}
}
diff --git a/plugins/experimental/cachekey/cachekey.h
b/plugins/experimental/cachekey/cachekey.h
index 7e5ddb4..ed156fb 100644
--- a/plugins/experimental/cachekey/cachekey.h
+++ b/plugins/experimental/cachekey/cachekey.h
@@ -55,8 +55,8 @@ public:
void append(const String &);
void append(const char *s);
void append(const char *n, unsigned s);
- void appendPrefix(const String &prefix, Pattern &pattern);
- void appendPath();
+ void appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern
&prefixCaptureUri);
+ void appendPath(Pattern &pathCapture, Pattern &pathCaptureUri);
void appendHeaders(const ConfigHeaders &config);
void appendQuery(const ConfigQuery &config);
void appendCookies(const ConfigCookies &config);
diff --git a/plugins/experimental/cachekey/configs.cc
b/plugins/experimental/cachekey/configs.cc
index 7a459d1..f82ca29 100644
--- a/plugins/experimental/cachekey/configs.cc
+++ b/plugins/experimental/cachekey/configs.cc
@@ -333,10 +333,13 @@ Configs::init(int argc, char *argv[])
{const_cast<char
*>("include-headers"), optional_argument, 0, 'g'},
{const_cast<char
*>("include-cookies"), optional_argument, 0, 'h'},
{const_cast<char *>("ua-capture"),
optional_argument, 0, 'i'},
- {const_cast<char
*>("static-prefix"), optional_argument, 0, 'j'},
- {const_cast<char
*>("capture-prefix"), optional_argument, 0, 'k'},
- {const_cast<char *>("ua-whitelist"),
optional_argument, 0, 'l'},
- {const_cast<char *>("ua-blacklist"),
optional_argument, 0, 'm'},
+ {const_cast<char *>("ua-whitelist"),
optional_argument, 0, 'j'},
+ {const_cast<char *>("ua-blacklist"),
optional_argument, 0, 'k'},
+ {const_cast<char
*>("static-prefix"), optional_argument, 0, 'l'},
+ {const_cast<char
*>("capture-prefix"), optional_argument, 0, 'm'},
+ {const_cast<char
*>("capture-prefix-uri"), optional_argument, 0, 'n'},
+ {const_cast<char *>("capture-path"),
optional_argument, 0, 'o'},
+ {const_cast<char
*>("capture-path-uri"), optional_argument, 0, 'p'},
{0, 0, 0, 0}};
bool status = true;
@@ -386,25 +389,43 @@ Configs::init(int argc, char *argv[])
status = false;
}
break;
- case 'j': /* static-prefix */
+ case 'j': /* ua-whitelist */
+ if (!loadClassifiers(optarg, /* blacklist = */ false)) {
+ CacheKeyError("failed to load User-Agent pattern white-list '%s'",
optarg);
+ status = false;
+ }
+ break;
+ case 'k': /* ua-blacklist */
+ if (!loadClassifiers(optarg, /* blacklist = */ true)) {
+ CacheKeyError("failed to load User-Agent pattern black-list '%s'",
optarg);
+ status = false;
+ }
+ break;
+ case 'l': /* static-prefix */
_prefix.assign(optarg);
CacheKeyDebug("prefix='%s'", _prefix.c_str());
break;
- case 'k': /* capture-prefix */
- if (!_hostCapture.init(optarg)) {
- CacheKeyError("failed to initialize URI host:port capture pattern
'%s'", optarg);
+ case 'm': /* capture-prefix */
+ if (!_prefixCapture.init(optarg)) {
+ CacheKeyError("failed to initialize prefix URI host:port capture
pattern '%s'", optarg);
status = false;
}
break;
- case 'l': /* ua-whitelist */
- if (!loadClassifiers(optarg, /* blacklist = */ false)) {
- CacheKeyError("failed to load User-Agent pattern white-list '%s'",
optarg);
+ case 'n': /* capture-prefix-uri */
+ if (!_prefixCaptureUri.init(optarg)) {
+ CacheKeyError("failed to initialize prefix URI capture pattern '%s'",
optarg);
status = false;
}
break;
- case 'm': /* ua-blacklist */
- if (!loadClassifiers(optarg, /* blacklist = */ true)) {
- CacheKeyError("failed to load User-Agent pattern black-list '%s'",
optarg);
+ case 'o': /* capture-path */
+ if (!_pathCapture.init(optarg)) {
+ CacheKeyError("failed to initialize path capture pattern '%s'",
optarg);
+ status = false;
+ }
+ break;
+ case 'p': /* capture-path-uri */
+ if (!_pathCaptureUri.init(optarg)) {
+ CacheKeyError("failed to initialize path URI capture pattern '%s'",
optarg);
status = false;
}
break;
diff --git a/plugins/experimental/cachekey/configs.h
b/plugins/experimental/cachekey/configs.h
index c9e2080..3281c78 100644
--- a/plugins/experimental/cachekey/configs.h
+++ b/plugins/experimental/cachekey/configs.h
@@ -140,13 +140,16 @@ public:
bool finalize();
/* Make the following members public to avoid unnecessary accessors */
- ConfigQuery _query; /**< @brief query parameter related configuration */
- ConfigHeaders _headers; /**< @brief headers related configuration */
- ConfigCookies _cookies; /**< @brief cookies related configuration */
- Pattern _uaCapture; /**< @brief the capture groups and the replacement
string used for the User-Agent header capture */
- String _prefix; /**< @brief cache key prefix string */
- Pattern _hostCapture; /**< @brief cache key prefix captured from the URI
host:port */
- Classifier _classifier; /**< @brief blacklist and white-list classifier used
to classify User-Agent header */
+ ConfigQuery _query; /**< @brief query parameter related configuration
*/
+ ConfigHeaders _headers; /**< @brief headers related configuration */
+ ConfigCookies _cookies; /**< @brief cookies related configuration */
+ Pattern _uaCapture; /**< @brief the capture groups and the
replacement string used for the User-Agent header capture */
+ String _prefix; /**< @brief cache key prefix string */
+ Pattern _prefixCapture; /**< @brief cache key prefix captured from the
URI host:port */
+ Pattern _prefixCaptureUri; /**< @brief cache key prefix captured from the
URI as a whole */
+ Pattern _pathCapture; /**< @brief cache key element captured from the
URI path */
+ Pattern _pathCaptureUri; /**< @brief cache key element captured from the
URI as a whole */
+ Classifier _classifier; /**< @brief blacklist and white-list classifier
used to classify User-Agent header */
private:
/**
diff --git a/plugins/experimental/cachekey/plugin.cc
b/plugins/experimental/cachekey/plugin.cc
index 429769f..e86fa5c 100644
--- a/plugins/experimental/cachekey/plugin.cc
+++ b/plugins/experimental/cachekey/plugin.cc
@@ -95,7 +95,7 @@ TSRemapDoRemap(void *instance, TSHttpTxn txn,
TSRemapRequestInfo *rri)
CacheKey cachekey(txn, rri->requestBufp, rri->requestUrl,
rri->requestHdrp);
/* Append custom prefix or the host:port */
- cachekey.appendPrefix(config->_prefix, config->_hostCapture);
+ cachekey.appendPrefix(config->_prefix, config->_prefixCapture,
config->_prefixCaptureUri);
/* Classify User-Agent and append the class name to the cache key if
matched. */
cachekey.appendUaClass(config->_classifier);
@@ -109,8 +109,8 @@ TSRemapDoRemap(void *instance, TSHttpTxn txn,
TSRemapRequestInfo *rri)
/* Append cookies to the cache key. */
cachekey.appendCookies(config->_cookies);
- /* Append the path, @todo enhance */
- cachekey.appendPath();
+ /* Append the path to the cache key. */
+ cachekey.appendPath(config->_pathCapture, config->_pathCaptureUri);
/* Append query parameters to the cache key. */
cachekey.appendQuery(config->_query);
diff --git a/plugins/experimental/cachekey/tests/test_cachekey.py
b/plugins/experimental/cachekey/tests/test_cachekey.py
index 42a5102..a232f2b 100644
--- a/plugins/experimental/cachekey/tests/test_cachekey.py
+++ b/plugins/experimental/cachekey/tests/test_cachekey.py
@@ -191,21 +191,87 @@ prefix_bench = [
"cookies": [],
"key": "/test_prefix/{1}/path/to/object?a=1&b=2&c=3"
},
+ # Testing adding a capture prefix with replacement string defined
+ { "args":
"@pparam=--capture-prefix=/(test_prefix).*:([^\s\/]*)/$1_$2/",
+ "uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
+ "headers": [],
+ "cookies": [],
+ "key": "/test_prefix_{1}/path/to/object?a=1&b=2&c=3"
+ },
+ # Testing adding a capture prefix from URI to the cache key
+ { "args":
"@pparam=--capture-prefix-uri=(test_prefix).*:.*(object).*$",
+ "uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
+ "headers": [],
+ "cookies": [],
+ "key": "/test_prefix/object/path/to/object?a=1&b=2&c=3"
+ },
+ # Testing adding a capture prefix from with replacement string
defined
+ { "args":
"@pparam=--capture-prefix-uri=/(test_prefix).*:.*(object).*$/$1_$2/",
+ "uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
+ "headers": [],
+ "cookies": [],
+ "key": "/test_prefix_object/path/to/object?a=1&b=2&c=3"
+ },
# Testing adding both static and capture prefix to the cache key
- { "args": "@pparam=--static-prefix=static_prefix
@pparam=--capture-prefix=test_prefix",
+ { "args": "@pparam=--static-prefix=static_prefix
@pparam=--capture-prefix=(test_prefix).*",
"uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
"headers": [],
"cookies": [],
"key": "/static_prefix/test_prefix/path/to/object?a=1&b=2&c=3"
},
- # Testing adding a capture prefix with replacement string defined
- { "args":
"@pparam=--capture-prefix=/(test_prefix).*:([^\s\/]*)/$1_$2/",
+ # Testing adding static and capture prefix and capture prefix from
URI to the cache key
+ { "args": "@pparam=--static-prefix=static_prefix
@pparam=--capture-prefix=(test_prefix).*
@pparam=--capture-prefix-uri=(object).*",
"uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
"headers": [],
"cookies": [],
- "key": "/test_prefix_{1}/path/to/object?a=1&b=2&c=3"
+ "key":
"/static_prefix/test_prefix/object/path/to/object?a=1&b=2&c=3"
},
]
+path_bench = [
+ # Testing adding default path to the cache key
+ { "args": "",
+ "uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
+ "headers": [],
+ "cookies": [],
+ "key": "/{0}/{1}/path/to/object?a=1&b=2&c=3"
+ },
+ # Testing adding a path capture to the cache key
+ { "args": "@pparam=--capture-path=.*(object).*",
+ "uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
+ "headers": [],
+ "cookies": [],
+ "key": "/{0}/{1}/object?a=1&b=2&c=3"
+ },
+ # Testing adding a path capture/replacement to the cache key
+ { "args": "@pparam=--capture-path=/.*(object).*/const_path_$1/",
+ "uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
+ "headers": [],
+ "cookies": [],
+ "key": "/{0}/{1}/const_path_object?a=1&b=2&c=3"
+ },
+ # Testing adding an URI capture to the cache key
+ { "args": "@pparam=--capture-path-uri=(test_path).*(object).*",
+ "uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
+ "headers": [],
+ "cookies": [],
+ "key": "/{0}/{1}/test_path/object?a=1&b=2&c=3"
+ },
+ # Testing adding an URI capture/replacement to the cache key
+ { "args":
"@pparam=--capture-path-uri=/(test_path).*(object).*/$1_$2/",
+ "uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
+ "headers": [],
+ "cookies": [],
+ "key": "/{0}/{1}/test_path_object?a=1&b=2&c=3"
+ },
+ # Testing adding an URI and path capture/replacement together to
the cache key
+ { "args": "@pparam=--capture-path=/.*(object).*/const_path_$1/
@pparam=--capture-path-uri=/(test_path).*(object).*/$1_$2/",
+ "uri": "{0}:{1}/path/to/object?a=1&b=2&c=3",
+ "headers": [],
+ "cookies": [],
+ "key": "/{0}/{1}/test_path_object/const_path_object?a=1&b=2&c=3"
+ },
+ ]
+
# User-Agent header capture related tests. Doesn't use the meta_bench.
ua_captures_bench = [
@@ -431,7 +497,7 @@ class
StaticEnvironmentCase(tsqa.test_cases.EnvironmentCase):
'''
@classmethod
def getEnv(cls):
- layout = tsqa.environment.Layout('/opt/apache/trafficserver.cachekey')
+ layout = tsqa.environment.Layout('/opt/apache/trafficserver.TS-4183/')
env = tsqa.environment.Environment()
env.clone(layout=layout)
return env
@@ -449,7 +515,6 @@ class TestCacheKey(tsqa.test_cases.DynamicHTTPEndpointCase,
StaticEnvironmentCas
cls.configs['records.config']['CONFIG'].update({
'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': '.*',
'proxy.config.diags.debug.tags': 'cachekey.*',
'proxy.config.url_remap.pristine_host_hdr': 1,
})
@@ -497,6 +562,12 @@ class
TestCacheKey(tsqa.test_cases.DynamicHTTPEndpointCase, StaticEnvironmentCas
add_remap_rule("prefix", i, test)
i+=1
+ # Prepare path tests related remap rules.
+ i = 0
+ for test in path_bench:
+ add_remap_rule("path", i, test)
+ i+=1
+
# Prepare ua-capture tests related remap rules.
i = 0
for test in ua_captures_bench:
@@ -577,16 +648,28 @@ class
TestCacheKey(tsqa.test_cases.DynamicHTTPEndpointCase, StaticEnvironmentCas
def test_cachekey_preffix(self):
'''
- Tests --static-prefix plugin option for replacing host:port with a
static prefix in the cache key.
+ Tests --static-prefix, --capture-prefix, --capture-prefix-uri plugin
option in the cache key.
'''
global prifix_bench
- log.info("Testing replacing host:port with a static prefix in the
cache key creation.")
+ log.info("Testing --static-prefix, --capture-prefix,
--capture-prefix-uri plugin option in the cache key.")
i = 0
for test in prefix_bench:
self.verify_key('prefix', i, test)
i += 1
+ def test_cachekey_path(self):
+ '''
+ Tests --path-capture, --path-capture-uri plugin option for replacing
path in the cache key.
+ '''
+ global path_bench
+
+ log.info("Testing --path-capture, --path-capture-uri plugin option for
replacing path in the cache key.")
+ i = 0
+ for test in path_bench:
+ self.verify_key('path', i, test)
+ i += 1
+
def test_cachekey_headers(self):
'''
Testing cache key headers handling.
--
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].