You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by sh...@apache.org on 2021/01/05 15:56:44 UTC
[trafficserver] branch master updated: API - Add new api function
TSHttpTxnServerSsnTransactionCount() to retrieve the number of transactions
between TS proxy and the origin server from a single session. (#7387)
This is an automated email from the ASF dual-hosted git repository.
shinrich 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 e175606 API - Add new api function TSHttpTxnServerSsnTransactionCount() to retrieve the number of transactions between TS proxy and the origin server from a single session. (#7387)
e175606 is described below
commit e175606bbd89f77400107b97f39cdd460e7c9a7a
Author: Damian Meden <da...@gmail.com>
AuthorDate: Tue Jan 5 15:56:30 2021 +0000
API - Add new api function TSHttpTxnServerSsnTransactionCount() to retrieve the number of transactions between TS proxy and the origin server from a single session. (#7387)
---
doc/admin-guide/plugins/header_rewrite.en.rst | 9 +++
.../TSHttpTxnServerSsnTransactionCount.en.rst | 37 +++++++++
include/ts/ts.h | 9 +++
plugins/header_rewrite/conditions.cc | 34 ++++++++
plugins/header_rewrite/conditions.h | 19 +++++
plugins/header_rewrite/factory.cc | 2 +
src/traffic_server/InkAPI.cc | 10 +++
src/traffic_server/InkAPITest.cc | 19 ++++-
.../gold/header_rewrite_cond_ssn_txn_count.gold | 71 +++++++++++++++++
.../header_rewrite_cond_ssn_txn_count.test.py | 90 ++++++++++++++++++++++
.../rules/rule_set_header_after_ssn_txn_count.conf | 19 +++++
11 files changed, 318 insertions(+), 1 deletion(-)
diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst
index 1bc8935..9db100a 100644
--- a/doc/admin-guide/plugins/header_rewrite.en.rst
+++ b/doc/admin-guide/plugins/header_rewrite.en.rst
@@ -482,6 +482,15 @@ Refer to `Requests vs. Responses`_ for more information on determining the
context in which the transaction's URL is evaluated. The ``<part>`` may be
specified according to the options documented in `URL Parts`_.
+SSN-TXN-COUNT
+~~~~~~~~~~~~~
+::
+
+ cond %{SSN-TXN-COUNT} <operand>
+
+Returns the number of transactions between the Traffic Server proxy and the origin server from a single session.
+Any value greater than zero indicates connection reuse.
+
Condition Operands
------------------
diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerSsnTransactionCount.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerSsnTransactionCount.en.rst
new file mode 100644
index 0000000..3035ea7
--- /dev/null
+++ b/doc/developer-guide/api/functions/TSHttpTxnServerSsnTransactionCount.en.rst
@@ -0,0 +1,37 @@
+.. 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:: ../../../common.defs
+
+.. default-domain:: c
+
+TSHttpTxnServerSsnTransactionCount
+**********************************
+
+Synopsis
+========
+
+.. code-block:: cpp
+
+ #include <ts/ts.h>
+
+.. function:: int TSHttpTxnServerSsnTransactionCount(TSHttpTxn txnp)
+
+Description
+===========
+
+Gets the number of transactions between the Traffic Server proxy and the origin server from a single session.
+Any value greater than zero indicates connection reuse.
diff --git a/include/ts/ts.h b/include/ts/ts.h
index 4c4565e..082eda1 100644
--- a/include/ts/ts.h
+++ b/include/ts/ts.h
@@ -1313,6 +1313,15 @@ tsapi TSReturnCode TSHttpTxnCachedRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLo
tsapi TSReturnCode TSHttpTxnPristineUrlGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *url_loc);
+/**
+ * @brief Gets the number of transactions between the Traffic Server proxy and the origin server from a single session.
+ * Any value greater than zero indicates connection reuse.
+ *
+ * @param txnp The transaction
+ * @return int The number of transactions between the Traffic Server proxy and the origin server from a single session
+ */
+tsapi int TSHttpTxnServerSsnTransactionCount(TSHttpTxn txnp);
+
/** Get the effective URL for the transaction.
The effective URL is the URL taking in to account both the explicit
URL in the request and the HOST field.
diff --git a/plugins/header_rewrite/conditions.cc b/plugins/header_rewrite/conditions.cc
index b9df7b8..84ce254 100644
--- a/plugins/header_rewrite/conditions.cc
+++ b/plugins/header_rewrite/conditions.cc
@@ -1300,3 +1300,37 @@ ConditionStringLiteral::eval(const Resources &res)
return static_cast<const MatcherType *>(_matcher)->test(_literal);
}
+
+// ConditionSessionTransactCount
+void
+ConditionSessionTransactCount::initialize(Parser &p)
+{
+ Condition::initialize(p);
+ MatcherType *match = new MatcherType(_cond_op);
+ std::string const &arg = p.get_arg();
+
+ match->set(strtol(arg.c_str(), nullptr, 10));
+ _matcher = match;
+}
+
+bool
+ConditionSessionTransactCount::eval(const Resources &res)
+{
+ int const val = TSHttpTxnServerSsnTransactionCount(res.txnp);
+
+ TSDebug(PLUGIN_NAME, "Evaluating SSN-TXN-COUNT()");
+ return static_cast<MatcherType *>(_matcher)->test(val);
+}
+
+void
+ConditionSessionTransactCount::append_value(std::string &s, Resources const &res)
+{
+ char value[32]; // enough for UINT64_MAX
+ int const count = TSHttpTxnServerSsnTransactionCount(res.txnp);
+ int const length = ink_fast_itoa(count, value, sizeof(value));
+
+ if (length > 0) {
+ TSDebug(PLUGIN_NAME, "Appending SSN-TXN-COUNT %s to evaluation value %.*s", _qualifier.c_str(), length, value);
+ s.append(value, length);
+ }
+}
\ No newline at end of file
diff --git a/plugins/header_rewrite/conditions.h b/plugins/header_rewrite/conditions.h
index 927c823..03f42d4 100644
--- a/plugins/header_rewrite/conditions.h
+++ b/plugins/header_rewrite/conditions.h
@@ -544,3 +544,22 @@ protected:
private:
std::string _literal;
};
+
+// Single Session Transaction Count
+class ConditionSessionTransactCount : public Condition
+{
+ typedef Matchers<int> MatcherType;
+
+public:
+ ConditionSessionTransactCount() { TSDebug(PLUGIN_NAME_DBG, "ConditionSessionTransactCount()"); }
+
+ // noncopyable
+ ConditionSessionTransactCount(const ConditionSessionTransactCount &) = delete;
+ void operator=(const ConditionSessionTransactCount &) = delete;
+
+ void initialize(Parser &p) override;
+ void append_value(std::string &s, const Resources &res) override;
+
+protected:
+ bool eval(const Resources &res) override;
+};
\ No newline at end of file
diff --git a/plugins/header_rewrite/factory.cc b/plugins/header_rewrite/factory.cc
index 0d314e4..a5decc7 100644
--- a/plugins/header_rewrite/factory.cc
+++ b/plugins/header_rewrite/factory.cc
@@ -137,6 +137,8 @@ condition_factory(const std::string &cond)
c = new ConditionCidr();
} else if (c_name == "INBOUND") {
c = new ConditionInbound();
+ } else if (c_name == "SSN-TXN-COUNT") {
+ c = new ConditionSessionTransactCount();
} else {
TSError("[%s] Unknown condition %s", PLUGIN_NAME, c_name.c_str());
return nullptr;
diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc
index 178fe15..5f529c2 100644
--- a/src/traffic_server/InkAPI.cc
+++ b/src/traffic_server/InkAPI.cc
@@ -5093,6 +5093,16 @@ TSHttpTxnPristineUrlGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *url_loc)
return TS_ERROR;
}
+int
+TSHttpTxnServerSsnTransactionCount(TSHttpTxn txnp)
+{
+ sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
+
+ HttpSM *sm = (HttpSM *)txnp;
+ // Any value greater than zero indicates connection reuse.
+ return sm->server_transact_count;
+}
+
// Shortcut to just get the URL.
// The caller is responsible to free memory that is allocated for the string
// that is returned.
diff --git a/src/traffic_server/InkAPITest.cc b/src/traffic_server/InkAPITest.cc
index d8211df..f864830 100644
--- a/src/traffic_server/InkAPITest.cc
+++ b/src/traffic_server/InkAPITest.cc
@@ -3034,6 +3034,7 @@ REGRESSION_TEST(SDK_API_TSContSchedule)(RegressionTest *test, int /* atype ATS_U
// TSHttpTxnNextHopAddrGet
// TSHttpTxnClientProtocolStackGet
// TSHttpTxnClientProtocolStackContains
+// TSHttpTxnServerSsnTransactionCount
//////////////////////////////////////////////////////////////////////////////
#define HTTP_HOOK_TEST_REQUEST_ID 1
@@ -3375,6 +3376,22 @@ checkHttpTxnServerRespGet(SocketTest *test, void *data)
return TS_EVENT_CONTINUE;
}
+// This func is called by us from mytest_handler to test TSHttpTxnServerSsnTransactionCount
+static int
+checkHttpTxnServerSsnTransactionCount(SocketTest *test, void *data)
+{
+ TSHttpTxn txnp = (TSHttpTxn)data;
+
+ int count = TSHttpTxnServerSsnTransactionCount(txnp);
+ if (count < 0) {
+ SDK_RPRINT(test->regtest, "TSHttpTxnServerSsnTransactionCount", "TestCase1", TC_FAIL, "invalid count value '%d'", count);
+ } else {
+ SDK_RPRINT(test->regtest, "TSHttpTxnServerSsnTransactionCount", "TestCase1", TC_PASS, "ok - count='%d'", count);
+ }
+
+ return count;
+}
+
// This func is called both by us when scheduling EVENT_IMMEDIATE
// And by HTTP SM for registered hooks
// Depending on the timing of the DNS response, OS_DNS can happen before or after CACHE_LOOKUP.
@@ -3455,6 +3472,7 @@ mytest_handler(TSCont contp, TSEvent event, void *data)
test->hook_mask |= 32;
}
checkHttpTxnServerRespGet(test, data);
+ checkHttpTxnServerSsnTransactionCount(test, data);
TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
test->reenable_mask |= 32;
@@ -3466,7 +3484,6 @@ mytest_handler(TSCont contp, TSEvent event, void *data)
}
checkHttpTxnClientRespGet(test, data);
-
TSHttpTxnReenable(static_cast<TSHttpTxn>(data), TS_EVENT_HTTP_CONTINUE);
test->reenable_mask |= 64;
break;
diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite_cond_ssn_txn_count.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite_cond_ssn_txn_count.gold
new file mode 100644
index 0000000..482d736
--- /dev/null
+++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite_cond_ssn_txn_count.gold
@@ -0,0 +1,71 @@
+``
+> GET /hello HTTP/1.1
+> Host: www.example.com
+> User-Agent: curl/``
+> Accept: */*
+> Connection: keep-alive
+``
+< HTTP/1.1 200 OK
+< Server: ATS/``
+< Content-Length: ``0``
+< Date: ``
+< Age: ``
+< Connection: keep-alive
+<
+``
+> GET /hello HTTP/1.1
+> Host: www.example.com
+> User-Agent: curl/``
+> Accept: */*
+> Connection: keep-alive
+``
+< HTTP/1.1 200 OK
+< Server: ATS/``
+< Content-Length: ``0``
+< Date: ``
+< Age: ``
+< Connection: keep-alive
+<
+``
+> GET /hello HTTP/1.1
+> Host: www.example.com
+> User-Agent: curl/``
+> Accept: */*
+> Connection: keep-alive
+``
+< HTTP/1.1 200 OK
+< Server: ATS/``
+< Content-Length: ``0``
+< Date: ``
+< Age: ``
+< Connection: keep-alive
+<
+``
+> GET /hello HTTP/1.1
+> Host: www.example.com
+> User-Agent: curl/``
+> Accept: */*
+> Connection: keep-alive
+``
+< HTTP/1.1 200 OK
+< Server: ATS/``
+< Content-Length: ``0``
+< Date: ``
+< Age: ``
+< Connection: close
+<
+``
+> GET /world HTTP/1.1
+> Host: www.example.com
+> User-Agent: curl/``
+> Accept: */*
+> Connection: close
+``
+< HTTP/1.1 200 OK
+< Server: ATS/``
+< Content-Length: ``0``
+< Date: ``
+< Age: ``
+< Connection: close
+<
+``
\ No newline at end of file
diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_cond_ssn_txn_count.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_cond_ssn_txn_count.test.py
new file mode 100644
index 0000000..73dd6b6
--- /dev/null
+++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_cond_ssn_txn_count.test.py
@@ -0,0 +1,90 @@
+'''
+Test adding a close connection header when SSN-TXN-COUNT reach a limit
+'''
+# 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.
+
+ts = Test.MakeATSProcess("ts")
+server = Test.MakeOriginServer("server")
+
+Test.testName = "SSN-TXN-COUNT"
+
+# Test SSN-TXN-COUNT condition.
+request_header_hello = {"headers":
+ "GET /hello HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 0\r\n\r\n",
+ "timestamp": "1469733493.993", "body": ""}
+response_header_hello = {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\n"
+ "Content-Length: 0\r\n\r\n",
+ "timestamp": "1469733493.993", "body": ""}
+
+request_header_world = {"headers": "GET /world HTTP/1.1\r\nContent-Length: 0\r\n"
+ "Host: www.example.com\r\n\r\n",
+ "timestamp": "1469733493.993", "body": "a\r\na\r\na\r\n\r\n"}
+response_header_world = {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\n"
+ "Connection: close\r\nContent-Length: 0\r\n\r\n",
+ "timestamp": "1469733493.993", "body": ""}
+
+# add request/response
+server.addResponse("sessionlog.log", request_header_hello, response_header_hello)
+server.addResponse("sessionlog.log", request_header_world, response_header_world)
+
+ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'header.*',
+ 'proxy.config.http.auth_server_session_private': 1,
+ 'proxy.config.http.server_session_sharing.pool': 'global',
+ 'proxy.config.http.server_session_sharing.match': 'both',
+})
+
+# In case we need this in the future, just remove the comments.
+# ts.Disk.logging_yaml.AddLines(
+# '''
+# logging:
+# formats:
+# - name: long
+# format: "SSTC:%<sstc>"
+# logs:
+# - filename: rewrite.log.txt
+# format: long
+# '''.split("\n")
+# )
+
+# This rule adds the connection header to close it after the number of transactions from a single
+# session is > 2. This test the new SSN-TXN-COUNT condition.
+ts.Setup.CopyAs('rules/rule_set_header_after_ssn_txn_count.conf', Test.RunDirectory)
+
+ts.Disk.remap_config.AddLine(
+ 'map / http://127.0.0.1:{0} @plugin=header_rewrite.so @pparam={1}/rule_set_header_after_ssn_txn_count.conf'.format(
+ server.Variables.Port, Test.RunDirectory))
+
+curlRequest = (
+ 'curl -v -H\'Host: www.example.com\' -H\'Connection: keep-alive\' http://127.0.0.1:{0}/hello &&'
+ 'curl -v -H\'Host: www.example.com\' -H\'Connection: keep-alive\' http://127.0.0.1:{0}/hello &&'
+ 'curl -v -H\'Host: www.example.com\' -H\'Connection: keep-alive\' http://127.0.0.1:{0}/hello &&'
+ 'curl -v -H\'Host: www.example.com\' -H\'Connection: keep-alive\' http://127.0.0.1:{0}/hello &&'
+ # I have to force last one with close connection header, this is also reflected in the response ^.
+ # if I do not do this, then the microserver will fail to close and when shutting down the process will
+ # fail with -9.
+ 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.0.1:{0}/world'
+)
+
+tr = Test.AddTestRun("Add connection close header when ssn-txn-count > 2")
+tr.Processes.Default.Command = curlRequest.format(ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.StartBefore(server)
+tr.Processes.Default.StartBefore(ts)
+tr.Processes.Default.Streams.stderr = "gold/header_rewrite_cond_ssn_txn_count.gold"
+tr.StillRunningAfter = server
diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_header_after_ssn_txn_count.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_header_after_ssn_txn_count.conf
new file mode 100644
index 0000000..ab3fdd3
--- /dev/null
+++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_header_after_ssn_txn_count.conf
@@ -0,0 +1,19 @@
+#
+# 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.
+cond %{SEND_RESPONSE_HDR_HOOK} [AND]
+ cond %{SSN-TXN-COUNT} >2
+ set-header Connection close
\ No newline at end of file