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 <kic...@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 +``