You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2022/07/13 20:18:47 UTC
[trafficserver] branch 9.2.x updated: ESI processing when origin returns 304 response (#8563)
This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch 9.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/9.2.x by this push:
new f8a900f0d ESI processing when origin returns 304 response (#8563)
f8a900f0d is described below
commit f8a900f0d6e8b0ca9fa8eabbbafcbb8a571b7122
Author: Kit Chan <ki...@apache.org>
AuthorDate: Tue Jan 18 16:43:00 2022 -0800
ESI processing when origin returns 304 response (#8563)
* ESI processing when origin returns 304 response
* Fix gold tests
(cherry picked from commit c0e3ddb985689ae2f71ca486421caf67cc83cfc3)
---
plugins/esi/esi.cc | 14 ++
tests/gold_tests/pluginTest/esi/esi_304.test.py | 210 +++++++++++++++++++++
.../pluginTest/esi/gold/esi_private_headers.gold | 7 +
3 files changed, 231 insertions(+)
diff --git a/plugins/esi/esi.cc b/plugins/esi/esi.cc
index 9d223b5f9..3b29f83ce 100644
--- a/plugins/esi/esi.cc
+++ b/plugins/esi/esi.cc
@@ -1292,6 +1292,20 @@ isTxnTransformable(TSHttpTxn txnp, bool is_cache_txn, bool *intercept_header, bo
return false;
}
+ // if origin returns status 304, check cached response instead
+ int response_status;
+ if (is_cache_txn == false) {
+ response_status = TSHttpHdrStatusGet(bufp, hdr_loc);
+ if (response_status == TS_HTTP_STATUS_NOT_MODIFIED) {
+ TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+ header_obtained = TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc);
+ if (header_obtained != TS_SUCCESS) {
+ TSError("[esi][%s] Couldn't get txn cache response header", __FUNCTION__);
+ return false;
+ }
+ }
+ }
+
do {
*intercept_header = checkHeaderValue(bufp, hdr_loc, SERVER_INTERCEPT_HEADER, SERVER_INTERCEPT_HEADER_LEN);
if (*intercept_header) {
diff --git a/tests/gold_tests/pluginTest/esi/esi_304.test.py b/tests/gold_tests/pluginTest/esi/esi_304.test.py
new file mode 100644
index 000000000..a078f84da
--- /dev/null
+++ b/tests/gold_tests/pluginTest/esi/esi_304.test.py
@@ -0,0 +1,210 @@
+'''
+Test the ESI plugin when origin returns 304 response.
+'''
+# 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.
+
+import os
+
+Test.Summary = '''
+Test the ESI plugin when origin returns 304 response.
+'''
+
+Test.SkipUnless(
+ Condition.PluginExists('esi.so'),
+)
+
+
+class EsiTest():
+ """
+ A class that encapsulates the configuration and execution of a set of ESI
+ test cases.
+ """
+
+ """ static: The same server Process is used across all tests. """
+ _server = None
+
+ """ static: A counter to keep the ATS process names unique across tests. """
+ _ts_counter = 0
+
+ """ static: A counter to keep any output file names unique across tests. """
+ _output_counter = 0
+
+ """ The ATS process for this set of test cases. """
+ _ts = None
+
+ def __init__(self, plugin_config):
+ """
+ Args:
+ plugin_config (str): The config line to place in plugin.config for
+ the ATS process.
+ """
+ if EsiTest._server is None:
+ EsiTest._server = EsiTest._create_server()
+
+ self._ts = EsiTest._create_ats(self, plugin_config)
+
+ @staticmethod
+ def _create_server():
+ """
+ Create and start a server process.
+ """
+ # Configure our server.
+ server = Test.MakeOriginServer("server", lookup_key="{%uuid}")
+
+ # Generate the set of ESI responses.
+ request_header = {
+ "headers":
+ "GET /esi_etag.php HTTP/1.1\r\n" +
+ "Host: www.example.com\r\n" +
+ "uuid: first\r\n" +
+ "Content-Length: 0\r\n\r\n",
+ "timestamp": "1469733493.993",
+ "body": ""
+ }
+ esi_body = r'''<html>
+<body>
+Hello, ESI 304 test
+</body>
+</html>
+'''
+ response_header = {
+ "headers":
+ "HTTP/1.1 200 OK\r\n" +
+ "X-Esi: 1\r\n" +
+ "Cache-Control: public, max-age=0\r\n" +
+ 'Etag: "esi_304_test"\r\n' +
+ "Content-Type: text/html\r\n" +
+ "Connection: close\r\n" +
+ "Content-Length: {}\r\n".format(len(esi_body)) +
+ "\r\n",
+ "timestamp": "1469733493.993",
+ "body": esi_body
+ }
+ server.addResponse("sessionfile.log", request_header, response_header)
+
+ request_header = {
+ "headers":
+ "GET /esi_etag.php HTTP/1.1\r\n" +
+ "Host: www.example.com\r\n" +
+ "uuid: second\r\n" +
+ 'If-None-Match: "esi_304_test"\r\n' +
+ "Content-Length: 0\r\n\r\n",
+ "timestamp": "1469733493.993",
+ "body": ""
+ }
+ response_header = {
+ "headers":
+ "HTTP/1.1 304 Not Modified\r\n" +
+ "Content-Type: text/html\r\n" +
+ "Connection: close\r\n" +
+ "Content-Length: 0\r\n" +
+ "\r\n",
+ "timestamp": "1469733493.993",
+ "body": ""
+ }
+ server.addResponse("sessionfile.log", request_header, response_header)
+
+ request_header = {
+ "headers":
+ "GET /date.php HTTP/1.1\r\n" +
+ "Host: www.example.com\r\n" +
+ "uuid: date\r\n" +
+ "Content-Length: 0\r\n\r\n",
+ "timestamp": "1469733493.993",
+ "body": ""
+ }
+ date_body = r'''ESI 304 test
+No Date
+'''
+ response_header = {
+ "headers":
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-Type: text/html\r\n" +
+ "Connection: close\r\n" +
+ "Content-Length: {}\r\n".format(len(date_body)) +
+ "\r\n",
+ "timestamp": "1469733493.993",
+ "body": date_body
+ }
+ server.addResponse("sessionfile.log", request_header, response_header)
+
+ # Create a run to start the server.
+ tr = Test.AddTestRun("Start the server.")
+ tr.Processes.Default.StartBefore(server)
+ tr.Processes.Default.Command = "echo starting the server"
+ tr.Processes.Default.ReturnCode = 0
+ tr.StillRunningAfter = server
+
+ return server
+
+ @staticmethod
+ def _create_ats(self, plugin_config):
+ """
+ Create and start an ATS process.
+ """
+ EsiTest._ts_counter += 1
+
+ # Configure ATS with a vanilla ESI plugin configuration.
+ ts = Test.MakeATSProcess("ts{}".format(EsiTest._ts_counter))
+ ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'http|plugin_esi',
+ })
+ ts.Disk.remap_config.AddLine(
+ 'map http://www.example.com/ http://127.0.0.1:{0}'.format(EsiTest._server.Variables.Port)
+ )
+ ts.Disk.plugin_config.AddLine(plugin_config)
+
+ # Create a run to start the ATS process.
+ tr = Test.AddTestRun("Start the ATS process.")
+ tr.Processes.Default.StartBefore(ts)
+ tr.Processes.Default.Command = "echo starting ATS"
+ tr.Processes.Default.ReturnCode = 0
+ tr.StillRunningAfter = ts
+ return ts
+
+ def run_cases(self):
+ # Test 1: Verify basic ESI functionality.
+ tr = Test.AddTestRun("First request for esi_etag.php: not cached")
+ tr.Processes.Default.Command = \
+ ('curl http://127.0.0.1:{0}/esi_etag.php -H"Host: www.example.com" '
+ '-H"Accept: */*" -H"uuid: first" --verbose -o /dev/stderr'.format(
+ self._ts.Variables.port))
+ tr.Processes.Default.ReturnCode = 0
+ tr.Processes.Default.Streams.stderr = "gold/esi_private_headers.gold"
+ tr.StillRunningAfter = self._server
+ tr.StillRunningAfter = self._ts
+
+ # Test 2: Repeat the above, origin should now be returning 304 response.
+ tr = Test.AddTestRun("Second request for esi_etag.php: will be cached")
+ tr.Processes.Default.Command = \
+ ('curl http://127.0.0.1:{0}/esi_etag.php -H"Host: www.example.com" '
+ '-H"Accept: */*" -H"uuid: second" --verbose -o /dev/stderr'.format(
+ self._ts.Variables.port))
+ tr.Processes.Default.ReturnCode = 0
+ tr.Processes.Default.Streams.stderr = "gold/esi_private_headers.gold"
+ tr.StillRunningAfter = self._server
+ tr.StillRunningAfter = self._ts
+
+
+#
+# Configure and run the test cases.
+#
+
+# Run the tests with ESI configured with private response.
+private_response_test = EsiTest(plugin_config='esi.so --private-response')
+private_response_test.run_cases()
diff --git a/tests/gold_tests/pluginTest/esi/gold/esi_private_headers.gold b/tests/gold_tests/pluginTest/esi/gold/esi_private_headers.gold
new file mode 100644
index 000000000..caa77ec0d
--- /dev/null
+++ b/tests/gold_tests/pluginTest/esi/gold/esi_private_headers.gold
@@ -0,0 +1,7 @@
+``
+> GET /esi_etag.php HTTP/1.1
+``
+< HTTP/1.1 200 OK
+``
+< Cache-Control: max-age=0, private
+``