This is an automated email from the ASF dual-hosted git repository.
zwoop 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 6addcf4b2a Adds a HTTP-CNTL condition to header_rewrite (#11863)
6addcf4b2a is described below
commit 6addcf4b2ac7278dde466d4d7aa7042cd74fc1e6
Author: Leif Hedstrom <[email protected]>
AuthorDate: Thu Nov 14 21:00:31 2024 -0700
Adds a HTTP-CNTL condition to header_rewrite (#11863)
---
doc/admin-guide/plugins/header_rewrite.en.rst | 195 ++++++++++++++------------
plugins/header_rewrite/conditions.cc | 16 +++
plugins/header_rewrite/conditions.h | 32 +++++
plugins/header_rewrite/factory.cc | 2 +
plugins/header_rewrite/operators.cc | 29 +---
plugins/header_rewrite/statement.cc | 27 ++++
plugins/header_rewrite/statement.h | 1 +
7 files changed, 183 insertions(+), 119 deletions(-)
diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst
b/doc/admin-guide/plugins/header_rewrite.en.rst
index dcb99bf9cb..5de3dc7695 100644
--- a/doc/admin-guide/plugins/header_rewrite.en.rst
+++ b/doc/admin-guide/plugins/header_rewrite.en.rst
@@ -212,6 +212,41 @@ phase of the transaction. This happens when there is no
host in the incoming UR
and only set as a host header. During the remap phase the host header is
copied
to the CLIENT-URL. Use CLIENT-HEADER:Host if you are going to match the host.
+CIDR
+~~~~
+::
+
+ set-header @Client-CIDR %{CIDR:24,48}
+
+This condition takes the client IP, and applies the provided CIDR style masks
+to the IP, before producing a string. The typical use of this conditions is as
+above, producing a header that contains a IP representation which has some
+privacy properties. It can of course also be used as a regular condition, and
+the output is a string that can be compared against. The two optional
+arguments are as follows::
+
+ IPv4-Mask Length, in bits, of the IPv4 address to preserve. Default: 24
+ IPv6-Mask Length, in bits, of the IPv6 address to preserve. Default: 48
+
+The two arguments, if provided, are comma separated. Valid syntax includes::
+
+ %{CIDR} Defaults to 24,48 (as above)
+ %{CIDR:16} IPv4 CIDR mask is 16 bits, IPv6 mask is 48
+ %{CIDR:18,42} IPv4 CIDR mask is 18 bits, IPv6 mask is 42 bits
+
+A typical use case is to insert the @-prefixed header as above, and then use
+this header in a custom log format, rather than logging the full client
+IP. Another use case could be to make a special condition on a sub-net,
+e.g.::
+
+ cond %{CIDR:8} ="8.0.0.0"
+ set-header X-Is-Eight "Yes"
+ cond %{CIDR:,8} ="fd00::" #note the IPv6 Mask is in the second position
+ set-header IPv6Internal "true"
+
+This condition has no requirements other than access to the Client IP, hence,
+it should work in any and all hooks.
+
COOKIE
~~~~~~
::
@@ -237,32 +272,6 @@ Per-Mapping`_ above.
The ``<part>`` allows the operand to match against just a component of the URL,
as documented in `URL Parts`_ below.
-NEXT-HOP
-~~~~~~~~
-::
-
- cond %{NEXT-HOP:<part>} <operand>
-
-Returns next hop current selected parent information. The following qualifiers
-are supported::
-
- %{NEXT-HOP:HOST} Name of the current selected parent.
- %{NEXT-HOP:PORT} Port of the current selected parent.
-
-Note that the ``<part>`` of NEXT-HOP will likely not be available unless
-an origin server connection is attempted at which point it will available
-as part of the ``SEND_REQUEST_HDR_HOOK``.
-
-For example::
-
- cond %{SEND_REQUEST_HDR_HOOK} [AND]
- cond %{NEXT-HOP:HOST} =www.firstparent.com
- set-header Host vhost.firstparent.com
-
- cond %{SEND_REQUEST_HDR_HOOK} [AND]
- cond %{NEXT-HOP:HOST} =www.secondparent.com
- set-header Host vhost.secondparent.com
-
GEO
~~~
::
@@ -309,6 +318,20 @@ separated string of the values from every occurrence of
the header. Refer to
If you wish to use a client request header, regardless of hook context, you may
consider using the `CLIENT-HEADER`_ condition instead.
+HTTP-CNTL
+~~~~~~~~~
+::
+
+ cond %{HTTP-CNTL:<controller>}
+
+This condition allows you to check the state of various HTTP controls. The
controls
+are of the same name as for `set-http-cntl`. This condition returns a ``true``
or
+``false`` value, depending on the state of the control. For example::
+
+ cond %{HTTP-CNTL:LOGGING} [NOT]
+
+would only continue evaluation if logging is turned off.
+
ID
~~
::
@@ -329,41 +352,6 @@ arguments to another operator. For example::
set-header ATS-Req-UUID %{ID:UNIQUE}
-CIDR
-~~~~
-::
-
- set-header @Client-CIDR %{CIDR:24,48}
-
-This condition takes the client IP, and applies the provided CIDR style masks
-to the IP, before producing a string. The typical use of this conditions is as
-above, producing a header that contains a IP representation which has some
-privacy properties. It can of course also be used as a regular condition, and
-the output is a string that can be compared against. The two optional
-arguments are as follows::
-
- IPv4-Mask Length, in bits, of the IPv4 address to preserve. Default: 24
- IPv6-Mask Length, in bits, of the IPv6 address to preserve. Default: 48
-
-The two arguments, if provided, are comma separated. Valid syntax includes::
-
- %{CIDR} Defaults to 24,48 (as above)
- %{CIDR:16} IPv4 CIDR mask is 16 bits, IPv6 mask is 48
- %{CIDR:18,42} IPv4 CIDR mask is 18 bits, IPv6 mask is 42 bits
-
-A typical use case is to insert the @-prefixed header as above, and then use
-this header in a custom log format, rather than logging the full client
-IP. Another use case could be to make a special condition on a sub-net,
-e.g.::
-
- cond %{CIDR:8} ="8.0.0.0"
- set-header X-Is-Eight "Yes"
- cond %{CIDR:,8} ="fd00::" #note the IPv6 Mask is in the second position
- set-header IPv6Internal "true"
-
-This condition has no requirements other than access to the Client IP, hence,
-it should work in any and all hooks.
-
INBOUND
~~~~~~~
::
@@ -463,6 +451,32 @@ METHOD
The HTTP method (e.g. ``GET``, ``HEAD``, ``POST``, and so on) used by the
client for this transaction.
+NEXT-HOP
+~~~~~~~~
+::
+
+ cond %{NEXT-HOP:<part>} <operand>
+
+Returns next hop current selected parent information. The following qualifiers
+are supported::
+
+ %{NEXT-HOP:HOST} Name of the current selected parent.
+ %{NEXT-HOP:PORT} Port of the current selected parent.
+
+Note that the ``<part>`` of NEXT-HOP will likely not be available unless
+an origin server connection is attempted at which point it will available
+as part of the ``SEND_REQUEST_HDR_HOOK``.
+
+For example::
+
+ cond %{SEND_REQUEST_HDR_HOOK} [AND]
+ cond %{NEXT-HOP:HOST} =www.firstparent.com
+ set-header Host vhost.firstparent.com
+
+ cond %{SEND_REQUEST_HDR_HOOK} [AND]
+ cond %{NEXT-HOP:HOST} =www.secondparent.com
+ set-header Host vhost.secondparent.com
+
NOW
~~~
::
@@ -679,6 +693,24 @@ no-op
This operator does nothing, takes no arguments, and has no side effects.
+rm-destination
+~~~~~~~~~~~~~~
+::
+
+ rm-destination <part>
+
+Removes individual components of the remapped destination's address. When
+changing the remapped destination, ``<part>`` should be used to indicate the
+component that is being modified (see `URL Parts`_). Currently the only valid
+parts for rm-destination are QUERY, PATH, and PORT.
+
+For the query parameter, this operator takes an optional second argument,
+which is a list of query parameters to remove (or keep with ``[INV]``
modifier).
+
+::
+
+ rm-destination QUERY <comma separate list of query parameter>
+
rm-header
~~~~~~~~~
::
@@ -695,6 +727,15 @@ rm-cookie
Removes the cookie ``<name>``.
+run-plugin
+~~~~~~~~~~~~~~
+::
+
+ run-plugin <plugin-name>.so "<plugin-argument> ..."
+
+This allows to run an existing remap plugin, conditionally, from within a
+header rewrite rule.
+
set-body
~~~~~~~~
::
@@ -774,7 +815,7 @@ the appropriate logs even when the debug tag has not been
enabled. For
additional information on |TS| debugging statements, refer to
:ref:`developer-debug-tags` in the developer's documentation.
-**Note**: This operator is deprecated, use the ``set-http-cntl`` operator
instead,
+**Note**: This operator is deprecated, use the `set-http-cntl` operator
instead,
with the ``TXN_DEBUG`` control.
set-destination
@@ -790,34 +831,6 @@ used as its replacement. You must supply a non-zero length
value, otherwise
this operator will be an effective no-op (though a warning will be emitted to
the logs if debugging is enabled).
-rm-destination
-~~~~~~~~~~~~~~
-::
-
- rm-destination <part>
-
-Removes individual components of the remapped destination's address. When
-changing the remapped destination, ``<part>`` should be used to indicate the
-component that is being modified (see `URL Parts`_). Currently the only valid
-parts for rm-destination are QUERY, PATH, and PORT.
-
-For the query parameter, this operator takes an optional second argument,
-which is a list of query parameters to remove (or keep with ``[INV]``
modifier).
-
-::
-
- rm-destination QUERY <comma separate list of query parameter>
-
-
-run-plugin
-~~~~~~~~~~~~~~
-::
-
- run-plugin <plugin-name>.so "<plugin-argument> ..."
-
-This allows to run an existing remap plugin, conditionally, from within a
-header rewrite rule.
-
set-header
~~~~~~~~~~
::
@@ -886,7 +899,7 @@ When invoked, and when ``<value>`` is any of ``1``,
``true``, or ``TRUE``, this
operator causes |TS| to abort further request remapping. Any other value and
the operator will effectively be a no-op.
-**Note**: This operator is deprecated, use the ``set-http-cntl`` operator
instead,
+**Note**: This operator is deprecated, use the `set-http-cntl` operator
instead,
with the ``SKIP_REMAP`` control.
set-cookie
diff --git a/plugins/header_rewrite/conditions.cc
b/plugins/header_rewrite/conditions.cc
index 67ed1f7567..747d260211 100644
--- a/plugins/header_rewrite/conditions.cc
+++ b/plugins/header_rewrite/conditions.cc
@@ -1425,3 +1425,19 @@ ConditionNextHop::eval(const Resources &res)
return static_cast<const Matchers<std::string> *>(_matcher)->test(s);
}
+
+// ConditionHttpCntl: request header.
+void
+ConditionHttpCntl::initialize(Parser &p)
+{
+ Condition::initialize(p);
+}
+
+void
+ConditionHttpCntl::set_qualifier(const std::string &q)
+{
+ Condition::set_qualifier(q);
+
+ Dbg(pi_dbg_ctl, "\tParsing %%{HTTP-CNTL:%s}", q.c_str());
+ _http_cntl_qual = parse_http_cntl_qualifier(q);
+}
diff --git a/plugins/header_rewrite/conditions.h
b/plugins/header_rewrite/conditions.h
index c6e1ff5dfb..6568fbeba9 100644
--- a/plugins/header_rewrite/conditions.h
+++ b/plugins/header_rewrite/conditions.h
@@ -627,3 +627,35 @@ protected:
private:
NextHopQualifiers _next_hop_qual = NEXT_HOP_NONE;
};
+
+// HTTP CNTL
+class ConditionHttpCntl : public Condition
+{
+public:
+ explicit ConditionHttpCntl() { Dbg(dbg_ctl, "Calling CTOR for
ConditionHttpCntl"); }
+
+ // noncopyable
+ ConditionHttpCntl(const ConditionHttpCntl &) = delete;
+ void operator=(const ConditionHttpCntl &) = delete;
+
+ void initialize(Parser &p) override;
+ void set_qualifier(const std::string &q) override;
+
+ void
+ append_value(std::string &s, const Resources &res) override
+ {
+ s += TSHttpTxnCntlGet(res.txnp, _http_cntl_qual) ? "TRUE" : "FALSE";
+ Dbg(pi_dbg_ctl, "Evaluating HTTP-CNTL(%s)", _qualifier.c_str());
+ }
+
+protected:
+ bool
+ eval(const Resources &res) override
+ {
+ Dbg(pi_dbg_ctl, "Evaluating HTTP-CNTL()");
+ return TSHttpTxnCntlGet(res.txnp, _http_cntl_qual);
+ }
+
+private:
+ TSHttpCntlType _http_cntl_qual = TS_HTTP_CNTL_LOGGING_MODE;
+};
diff --git a/plugins/header_rewrite/factory.cc
b/plugins/header_rewrite/factory.cc
index 346265f893..85136f0b04 100644
--- a/plugins/header_rewrite/factory.cc
+++ b/plugins/header_rewrite/factory.cc
@@ -162,6 +162,8 @@ condition_factory(const std::string &cond)
c = new ConditionCache();
} else if (c_name == "NEXT-HOP") { // This condition adapts to the hook
c = new ConditionNextHop();
+ } else if (c_name == "HTTP-CNTL") { // This condition adapts to the hook
+ c = new ConditionHttpCntl();
} else {
TSError("[%s] Unknown condition %s", PLUGIN_NAME, c_name.c_str());
return nullptr;
diff --git a/plugins/header_rewrite/operators.cc
b/plugins/header_rewrite/operators.cc
index 189e39b83f..6f5a8dcbcc 100644
--- a/plugins/header_rewrite/operators.cc
+++ b/plugins/header_rewrite/operators.cc
@@ -1150,38 +1150,11 @@ OperatorSetDebug::exec(const Resources &res) const
return true;
}
-// OperatorSetHttpCntl
-TSHttpCntlType
-parse_cntl_qualifier(const std::string &q) // Helper function for parsing
modifiers
-{
- TSHttpCntlType qual = TS_HTTP_CNTL_LOGGING_MODE;
-
- if (q == "LOGGING") {
- qual = TS_HTTP_CNTL_LOGGING_MODE;
- } else if (q == "INTERCEPT_RETRY") {
- qual = TS_HTTP_CNTL_INTERCEPT_RETRY_MODE;
- } else if (q == "RESP_CACHEABLE") {
- qual = TS_HTTP_CNTL_RESPONSE_CACHEABLE;
- } else if (q == "REQ_CACHEABLE") {
- qual = TS_HTTP_CNTL_REQUEST_CACHEABLE;
- } else if (q == "SERVER_NO_STORE") {
- qual = TS_HTTP_CNTL_SERVER_NO_STORE;
- } else if (q == "TXN_DEBUG") {
- qual = TS_HTTP_CNTL_TXN_DEBUG;
- } else if (q == "SKIP_REMAP") {
- qual = TS_HTTP_CNTL_SKIP_REMAPPING;
- } else {
- TSError("[%s] Invalid HTTP-CNTL() qualifier: %s", PLUGIN_NAME, q.c_str());
- }
-
- return qual;
-}
-
void
OperatorSetHttpCntl::initialize(Parser &p)
{
Operator::initialize(p);
- _cntl_qual = parse_cntl_qualifier(p.get_arg());
+ _cntl_qual = parse_http_cntl_qualifier(p.get_arg());
std::string flag = p.copy_value();
diff --git a/plugins/header_rewrite/statement.cc
b/plugins/header_rewrite/statement.cc
index 69bacda1fe..92e9fb67b5 100644
--- a/plugins/header_rewrite/statement.cc
+++ b/plugins/header_rewrite/statement.cc
@@ -114,3 +114,30 @@ Statement::parse_url_qualifier(const std::string &q) const
return qual;
}
+
+// Parse HTTP CNTL qualifiers
+TSHttpCntlType
+Statement::parse_http_cntl_qualifier(const std::string &q) const
+{
+ TSHttpCntlType qual = TS_HTTP_CNTL_LOGGING_MODE;
+
+ if (q == "LOGGING") {
+ qual = TS_HTTP_CNTL_LOGGING_MODE;
+ } else if (q == "INTERCEPT_RETRY") {
+ qual = TS_HTTP_CNTL_INTERCEPT_RETRY_MODE;
+ } else if (q == "RESP_CACHEABLE") {
+ qual = TS_HTTP_CNTL_RESPONSE_CACHEABLE;
+ } else if (q == "REQ_CACHEABLE") {
+ qual = TS_HTTP_CNTL_REQUEST_CACHEABLE;
+ } else if (q == "SERVER_NO_STORE") {
+ qual = TS_HTTP_CNTL_SERVER_NO_STORE;
+ } else if (q == "TXN_DEBUG") {
+ qual = TS_HTTP_CNTL_TXN_DEBUG;
+ } else if (q == "SKIP_REMAP") {
+ qual = TS_HTTP_CNTL_SKIP_REMAPPING;
+ } else {
+ TSError("[%s] Invalid HTTP-CNTL() qualifier: %s", PLUGIN_NAME, q.c_str());
+ }
+
+ return qual;
+}
diff --git a/plugins/header_rewrite/statement.h
b/plugins/header_rewrite/statement.h
index 1b5798bff3..9055558531 100644
--- a/plugins/header_rewrite/statement.h
+++ b/plugins/header_rewrite/statement.h
@@ -152,6 +152,7 @@ protected:
UrlQualifiers parse_url_qualifier(const std::string &q) const;
NextHopQualifiers parse_next_hop_qualifier(const std::string &q) const;
+ TSHttpCntlType parse_http_cntl_qualifier(const std::string &q) const;
void
require_resources(const ResourceIDs ids)