From 98e7a0ef0681109ed9332e76361bd68ef02a695c Mon Sep 17 00:00:00 2001 From: Brian Neradt Date: Wed, 5 Nov 2025 21:03:56 +0000 Subject: [PATCH 1/2] ATSReplayTest: autests via replay.yaml For context, this continues the work started in #12371. The goal is to take full advantage of the autest extension capabilities to make writing ATS autests easier. This adds the Test.ATSReplayTest autest extensions so that tests can be written through a replay.yaml file that specifies both the configuration of the test processes as well as the HTTP Proxy Verifier traffic for the test. This patch updates the header_rewrite_bundle to use this new framework. --- .../autest-site/ats_replay.test.ext | 144 +++ .../header_rewrite/gold/client-url.gold | 14 - .../header_rewrite/gold/cond-elif.gold | 11 - .../header_rewrite/gold/cond_cache.gold | 43 - .../header_rewrite/gold/cond_cache_first.gold | 15 - .../header_rewrite/gold/cond_method.gold | 8 - .../gold/cond_ssn_txn_count.gold | 71 -- .../header_rewrite/gold/ext-sets.gold | 11 - .../gold/header_rewrite-303.gold | 14 - .../header_rewrite_effective_address.gold | 7 - .../gold/implicit_hook_fie.gold | 16 - .../gold/implicit_hook_no_fie.gold | 15 - .../gold/implicit_hook_prefix.gold | 16 - .../header_rewrite/gold/l_value.gold | 16 - .../gold/nested_ifs_definitely.gold | 18 - .../header_rewrite/gold/nested_ifs_else.gold | 17 - .../gold/nested_ifs_else_fie.gold | 19 - .../gold/nested_ifs_foo_bar.gold | 20 - .../gold/nested_ifs_foo_fie.gold | 21 - .../header_rewrite/gold/nested_ifs_maybe.gold | 18 - .../header_rewrite/gold/regex_both_match.gold | 12 - .../gold/regex_match2_only.gold | 10 - .../header_rewrite/gold/set-redirect.gold | 8 - .../header_rewrite/gold/set_body_empty.gold | 16 - .../header_rewrite/gold/set_body_status.gold | 16 - .../gold/set_body_status_stdout.gold | 1 - .../header_rewrite_bundle.replay.yaml | 996 ++++++++++++++++++ .../header_rewrite_bundle.test.py | 350 +----- 28 files changed, 1141 insertions(+), 782 deletions(-) create mode 100644 tests/gold_tests/autest-site/ats_replay.test.ext delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/client-url.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/cond-elif.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/cond_cache.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/cond_cache_first.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/cond_method.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/cond_ssn_txn_count.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/ext-sets.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-303.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite_effective_address.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_fie.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_no_fie.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_prefix.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/l_value.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_definitely.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_else.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_else_fie.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_foo_bar.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_foo_fie.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_maybe.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/regex_both_match.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/regex_match2_only.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/set-redirect.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/set_body_empty.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/set_body_status.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/set_body_status_stdout.gold create mode 100644 tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.replay.yaml diff --git a/tests/gold_tests/autest-site/ats_replay.test.ext b/tests/gold_tests/autest-site/ats_replay.test.ext new file mode 100644 index 00000000000..54f809a54f2 --- /dev/null +++ b/tests/gold_tests/autest-site/ats_replay.test.ext @@ -0,0 +1,144 @@ +''' +Implement general-purpose ATS test extensions using proxy verifier replay files. +''' +# 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. + +from typing import Optional +import os +import yaml + + +def configure_ats(obj: 'TestRun', server: 'Process', ats_config: dict, dns: Optional['Process'] = None): + '''Configure ATS per the configuration in the replay file. + + :param obj: The Test object to configure ATS for. + :param server: The Proxy Verifier Server process to use. + :param ats_config: The ATS configuration from the replay file. + :param dns: The DNS process to use. Optional. + :returns: The ATS process object. + ''' + name = ats_config.get('name', 'ts') + process_config = ats_config.get('process_config', {}) + ts = obj.MakeATSProcess(name, **process_config) + records_config = ats_config.get('records_config', {}) + ts.Disk.records_config.update(records_config) + remap_config = ats_config.get('remap_config', []) + for remap_entry in remap_config: + if isinstance(remap_entry, str): + ts.Disk.remap_config.AddLine(remap_entry) + elif isinstance(remap_entry, dict): + from_url = remap_entry['from'] + to_url = remap_entry['to'] + to_url = to_url.replace('{SERVER_HTTP_PORT}', str(server.Variables.http_port)) + to_url = to_url.replace('{SERVER_HTTPS_PORT}', str(server.Variables.https_port)) + plugins = remap_entry.get('plugins', []) + line = f'map {from_url} {to_url}' + for plugin in plugins: + line += f' @plugin={plugin["name"]}' + for arg in plugin["args"]: + line += f' @pparam={arg}' + ts.Disk.remap_config.AddLine(line) + if dns: + ts.Disk.records_config.update( + { + 'proxy.config.dns.nameservers': f'127.0.0.1:{dns.Variables.Port}', + 'proxy.config.dns.resolv_conf': 'NULL', + }) + + for item in ats_config.get('copy_to_config_dir', []): + item_path = os.path.join(obj.TestDirectory, item) + if os.path.isdir(item_path): + src_dir = item_path + dst_dir = os.path.join(ts.Variables.CONFIGDIR, item) + ts.Setup.MakeDir(dst_dir) + ts.Setup.Copy(src_dir, dst_dir) + else: + ts.Setup.CopyAs(item, ts.Variables.CONFIGDIR) + return ts + + +def ATSReplayTest(obj, replay_file: str): + '''Create a TestRun that configures ATS and runs HTTP traffic using the replay file. + + :param obj: The Test object to add the test run to. + :param replay_file: Replay file specifying the test configuraiton and test traffic. + :returns: The TestRun object. + ''' + + replay_path = replay_file if os.path.isabs(replay_file) else os.path.join(obj.TestDirectory, replay_file) + with open(replay_path, 'r') as f: + replay_config = yaml.load(f, Loader=yaml.FullLoader) + + # The user must specify the 'autest' node. + if not 'autest' in replay_config: + raise ValueError(f"Replay file {replay_file} does not contain 'autest' section") + autest_config = replay_config['autest'] + + tr = obj.AddTestRun(autest_config['description']) + + # Copy the specified files and directories down. + tr.Setup.Copy(replay_file, tr.RunDirectory) + + for files_to_copy in autest_config.get('files_to_copy', []): + tr.Setup.Copy(files_to_copy) + for dirs_to_copy in autest_config.get('dirs_to_copy', []): + tr.Setup.Copy(dirs_to_copy) + + # DNS configuration. + if 'dns' in autest_config: + dns_config = autest_config['dns'] + name = dns_config['name'] + if 'process_config' in dns_config: + process_config = dns_config['process_config'] + dns = tr.MakeDNServer(name, **process_config) + else: + dns = tr.MakeDNServer(name, default='127.0.0.1') + + # Proxy Verifier Server configuration. + if not 'server' in autest_config: + raise ValueError(f"Replay file {replay_file} does not contain 'autest.server' section") + server_config = autest_config['server'] + name = server_config['name'] + process_config = server_config.get('process_config', {}) + server = tr.AddVerifierServerProcess(name, replay_file, **process_config) + + # ATS configuration. + if not 'ats' in autest_config: + raise ValueError(f"Replay file {replay_file} does not contain 'autest.ats' section") + ats_config = autest_config['ats'] + enable_tls = ats_config.get('enable_tls', False) + ts = configure_ats(tr, server=server, ats_config=ats_config, dns=dns) + + # Proxy Verifier Client configuration. + if not 'client' in autest_config: + raise ValueError(f"Replay file {replay_file} does not contain 'autest.client' section") + client_config = autest_config['client'] + name = client_config.get('name', 'client') + process_config = client_config.get('process_config', {}) + https_ports = [ts.Variables.ssl_port] if enable_tls else None + client = tr.AddVerifierClientProcess( + name, replay_file, http_ports=[ts.Variables.port], https_ports=https_ports, **process_config) + + if dns: + ts.StartBefore(dns) + ts.StartBefore(server) + client.StartBefore(ts) + + return tr + + +ExtendTest(ATSReplayTest, name="ATSReplayTest") diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/client-url.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/client-url.gold deleted file mode 100644 index 4f2e58973b6..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/client-url.gold +++ /dev/null @@ -1,14 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -`` -< HTTP/1.1 304 Not Modified -< Date: `` -< Proxy-Connection: keep-alive -< Server: ATS/`` -< Cache-Control: no-store -< X-Pre-Else: Yes -< X-Testing: No -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/cond-elif.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/cond-elif.gold deleted file mode 100644 index cb9d993ccf7..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/cond-elif.gold +++ /dev/null @@ -1,11 +0,0 @@ -`` -> GET http://www.example.com/from_1/hrw-sets.png`` -> Host: www.example.com`` -> User-Agent: curl/`` -`` -< HTTP/1.1 200 OK -< Date: `` -`` -< X-Extension: Yes -< X-Testing: elif -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/cond_cache.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/cond_cache.gold deleted file mode 100644 index 691e868bb4c..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/cond_cache.gold +++ /dev/null @@ -1,43 +0,0 @@ -`` -> GET /from_5/ HTTP/1.1 -> Host: www.example.com -> User-Agent: curl/`` -> Accept: */* -`` -< HTTP/1.1 200 OK -< Cache-Control: max-age=5,public -< Content-Length: 6 -< Date: `` -< Age: `` -< Connection: keep-alive -< Server: ATS/{} -< Cache-Result: hit-fresh -`` -> GET /from_5/ HTTP/1.1 -> Host: www.example.com -> User-Agent: curl/`` -> Accept: */* -`` -< HTTP/1.1 200 OK -< Cache-Control: max-age=5,public -< Content-Length: 6 -< Date: `` -< Age: `` -< Connection: keep-alive -< Server: ATS/{} -< Cache-Result: hit-stale -`` -> GET /from_5/ HTTP/1.1 -> Host: www.example.com -> User-Agent: curl/`` -> Accept: */* -`` -< HTTP/1.1 200 OK -< Cache-Control: max-age=5,public -< Content-Length: 6 -< Date: `` -< Age: `` -< Connection: keep-alive -< Server: ATS/{} -< Cache-Result: hit-fresh -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/cond_cache_first.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/cond_cache_first.gold deleted file mode 100644 index d2187d01b33..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/cond_cache_first.gold +++ /dev/null @@ -1,15 +0,0 @@ -`` -> GET /from_5/ HTTP/1.1 -> Host: www.example.com -> User-Agent: curl/`` -> Accept: */* -`` -< HTTP/1.1 200 OK -< Cache-Control: max-age=5,public -< Content-Length: 6 -< Date: `` -< Age: `` -< Connection: keep-alive -< Server: ATS/{} -< Cache-Result: miss -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/cond_method.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/cond_method.gold deleted file mode 100644 index 0afb37beead..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/cond_method.gold +++ /dev/null @@ -1,8 +0,0 @@ -`` -> `` `` HTTP/1.1 -> Host: www.example.com -`` -< HTTP/1.1 200 OK -`` -< Via:`` -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/cond_ssn_txn_count.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/cond_ssn_txn_count.gold deleted file mode 100644 index 23997b81cb1..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/cond_ssn_txn_count.gold +++ /dev/null @@ -1,71 +0,0 @@ -`` -> GET /from_4/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 /from_4/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 /from_4/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 /from_4/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 /from_4/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 -< -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/ext-sets.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/ext-sets.gold deleted file mode 100644 index b3072467056..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/ext-sets.gold +++ /dev/null @@ -1,11 +0,0 @@ -`` -> GET http://www.example.com/from_1/hrw-sets.png`` -> Host: www.example.com`` -> User-Agent: curl/`` -`` -< HTTP/1.1 200 OK -< Date: `` -`` -< X-Extension: Yes -< X-Testing: Yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-303.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-303.gold deleted file mode 100644 index 971c4bcf781..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-303.gold +++ /dev/null @@ -1,14 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -`` -< HTTP/1.1 303 See Other -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite_effective_address.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite_effective_address.gold deleted file mode 100644 index 063298216b2..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite_effective_address.gold +++ /dev/null @@ -1,7 +0,0 @@ -`` -> Real-IP: 1.2.3.4 -`` -< HTTP/1.1 200 OK -`` -< Effective-IP: 1.2.3.4 -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_fie.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_fie.gold deleted file mode 100644 index 523bc694cbf..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_fie.gold +++ /dev/null @@ -1,16 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -> X-Fie: Fie -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-Response-Foo: Yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_no_fie.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_no_fie.gold deleted file mode 100644 index 4b3f6bba11f..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_no_fie.gold +++ /dev/null @@ -1,15 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-Response-Foo: No -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_prefix.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_prefix.gold deleted file mode 100644 index 4f7e6ea5886..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/implicit_hook_prefix.gold +++ /dev/null @@ -1,16 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -> X-Client-Foo: fOoBar -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-Response-Foo: Prefix -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/l_value.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/l_value.gold deleted file mode 100644 index 9e2e304abc6..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/l_value.gold +++ /dev/null @@ -1,16 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-First: First -< X-Last: Last -< -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_definitely.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_definitely.gold deleted file mode 100644 index aaa750a26e0..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_definitely.gold +++ /dev/null @@ -1,18 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -> X-Foo: definitely -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-When-200-Before: Yes -< X-Foo: Definitely -< X-When-200-After: Yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_else.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_else.gold deleted file mode 100644 index a04b910a7d2..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_else.gold +++ /dev/null @@ -1,17 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-When-200-Before: Yes -< X-Foo: Nothing -< X-When-200-After: Yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_else_fie.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_else_fie.gold deleted file mode 100644 index 09d4e47708d..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_else_fie.gold +++ /dev/null @@ -1,19 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -> X-Fie: fie -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-When-200-Before: Yes -< X-Foo: Nothing -< X-Fie-Anywhere: Yes -< X-When-200-After: Yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_foo_bar.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_foo_bar.gold deleted file mode 100644 index b583ca387dd..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_foo_bar.gold +++ /dev/null @@ -1,20 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -> X-Foo: foo -> X-Bar: bar -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-When-200-Before: Yes -< X-Foo: Yes -< X-Foo-And-Bar: Yes -< X-When-200-After: Yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_foo_fie.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_foo_fie.gold deleted file mode 100644 index 126f4bdade6..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_foo_fie.gold +++ /dev/null @@ -1,21 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -> X-Foo: foo -> X-Fie: fie -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-When-200-Before: Yes -< X-Foo: Yes -< X-Foo-And-Fie: Yes -< X-Fie-Anywhere: Yes -< X-When-200-After: Yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_maybe.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_maybe.gold deleted file mode 100644 index f975acf4b18..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/nested_ifs_maybe.gold +++ /dev/null @@ -1,18 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -> X-Foo: maybe -`` -< HTTP/1.1 200 OK -< Date: `` -< Age: `` -< Transfer-Encoding: chunked -< Proxy-Connection: keep-alive -< Server: ATS/`` -< X-When-200-Before: Yes -< X-Foo: Maybe -< X-When-200-After: Yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/regex_both_match.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/regex_both_match.gold deleted file mode 100644 index ef3b2570063..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/regex_both_match.gold +++ /dev/null @@ -1,12 +0,0 @@ -`` -> GET http://www.example.com/from_9/`` -> Host: www.example.com`` -> User-Agent: curl/`` -> X-Test1: Foobar`` -`` -< HTTP/1.1 200 OK -< Date: `` -`` -< X-Match: yes -< X-Match-2: yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/regex_match2_only.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/regex_match2_only.gold deleted file mode 100644 index 06217cd6cb4..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/regex_match2_only.gold +++ /dev/null @@ -1,10 +0,0 @@ -`` -> GET http://www.example.com/from_9/`` -> Host: www.example.com`` -> User-Agent: curl/`` -`` -< HTTP/1.1 200 OK -< Date: `` -`` -< X-Match-2: yes -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/set-redirect.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/set-redirect.gold deleted file mode 100644 index bd76250fcc0..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/set-redirect.gold +++ /dev/null @@ -1,8 +0,0 @@ -`` -> HEAD / HTTP/1.1 -> Host: no_path.com -`` -< HTTP/1.1 301 Redirect -`` -< Location: http://no_path.com?name=brian/ -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/set_body_empty.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/set_body_empty.gold deleted file mode 100644 index 385c4f5fdb5..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/set_body_empty.gold +++ /dev/null @@ -1,16 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -`` -< HTTP/1.1 200 OK -< Date: `` -< Proxy-Connection: keep-alive -< Server: ATS/`` -< Cache-Control: no-store -< Content-Type: text/html; charset=utf-8 -< Content-Language: en -< Content-Length: 0 -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/set_body_status.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/set_body_status.gold deleted file mode 100644 index 93988eb9d1b..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/set_body_status.gold +++ /dev/null @@ -1,16 +0,0 @@ -`` -> GET `` -> Host: www.example.com`` -> User-Agent: curl/`` -> Accept: */* -> Proxy-Connection: Keep-Alive -`` -< HTTP/1.1 200 OK -< Date: `` -< Proxy-Connection: keep-alive -< Server: ATS/`` -< Cache-Control: no-store -< Content-Type: text/html -< Content-Language: en -< Content-Length: 3 -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/set_body_status_stdout.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/set_body_status_stdout.gold deleted file mode 100644 index 08839f6bb29..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/set_body_status_stdout.gold +++ /dev/null @@ -1 +0,0 @@ -200 diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.replay.yaml b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.replay.yaml new file mode 100644 index 00000000000..d778c0c8c57 --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.replay.yaml @@ -0,0 +1,996 @@ +# 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. + +meta: + version: "1.0" + +# Configuration section for autest integration +autest: + description: 'Test header_rewrite with URL conditions and operators' + + dns: + name: 'dns' + + server: + name: 'server' + + client: + name: 'client' + process_config: + other_args: '--thread-limit 1' + + ats: + name: 'ts' + + copy_to_config_dir: + - 'rules' + + records_config: + proxy.config.http.insert_response_via_str: 0 + proxy.config.http.auth_server_session_private: 1 + proxy.config.http.server_session_sharing.pool: 'global' + proxy.config.http.server_session_sharing.match: 'both' + proxy.config.diags.debug.enabled: 1 + proxy.config.diags.debug.tags: 'header_rewrite' + + remap_config: + - from: "http://no_path.com/" + to: "http://no_path.com?name=brian/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/set_redirect.conf" + + - from: "http://www.example.com/from_1/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_1/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/rule_client.conf" + + - from: "http://www.example.com/from_2/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_2/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/rule_cond_method.conf" + + - from: "http://www.example.com/from_3/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_3/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/rule_l_value.conf" + + - from: "http://www.example.com/from_4/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_4/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/rule_set_header_after_ssn_txn_count.conf" + + - from: "http://www.example.com/from_5/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_5/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/rule_add_cache_result_header.conf" + + - from: "http://www.example.com/from_6/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_6/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/rule_effective_address.conf" + + - from: "http://www.example.com/from_7/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_7/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/rule.conf" + + - from: "http://www.example.com/from_8/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_8/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/implicit_hook.conf" + + - from: "http://www.example.com/from_9/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_9/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/regex_tests.conf" + + - from: "http://www.example.com/from_10/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_10/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/rule_empty_body.conf" + + - from: "http://www.example.com/from_11/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_11/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/rule_set_body_status.conf" + + - from: "http://www.example.com/from_12/" + to: "http://backend.ex:{SERVER_HTTP_PORT}/to_12/" + plugins: + - name: "header_rewrite.so" + args: + - "rules/nested_ifs.conf" + + + +# Proxy verifier sessions +sessions: + # Test 1: Setup cache hit for tests later +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_5/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 1 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + - [ Cache-Control, "max-age=5,public" ] + content: + size: 6 + data: "CACHED" + + proxy-response: + status: 200 + headers: + fields: + - [ Cache-Result, { value: "miss", as: equal } ] + + # Test 2: TO-URL redirect test +- transactions: + - client-request: + method: "HEAD" + version: "1.1" + url: / + headers: + fields: + - [ Host, no_path.com ] + - [ uuid, 2 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 301 + reason: Redirect + headers: + fields: + - [ Location, { value: "http://no_path.com?name=brian/", as: equal } ] + + # Test 3: CLIENT-URL test +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_1/hello?=foo=bar + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 3 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 304 + reason: "Not Modified" + headers: + fields: + - [ Cache-Control, { value: "no-store", as: equal } ] + - [ X-Pre-Else, { value: "Yes", as: equal } ] + - [ X-Testing, { value: "No", as: equal } ] + - [ X-Extension, { as: absent } ] + + # Test 4: sets matching +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_1/hrw-sets.png + headers: + fields: + - [ Host, www.example.com ] + - [ X-Testing, "foo,bar" ] + - [ uuid, 4 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-Extension, { value: "Yes", as: equal } ] + - [ X-Testing, { value: "Yes", as: equal } ] + - [ X-Pre-Else, { as: absent } ] + + # Test 5: elif condition +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_1/hrw-sets.png + headers: + fields: + - [ Host, www.example.com ] + - [ X-Testing, "elif" ] + - [ uuid, 5 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-Extension, { value: "Yes", as: equal } ] + - [ X-Testing, { value: "elif", as: equal } ] + - [ X-Pre-Else, { as: absent } ] + + # Test 6: cond method GET +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_2/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 6 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ Via, { as: present } ] + + # Test 7: cond method DELETE +- transactions: + - client-request: + method: "DELETE" + version: "1.1" + url: /from_2/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 7 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ Via, { as: present } ] + + # Test 8: End [L] #5423 +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_3/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 8 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-First, { value: "First", as: equal } ] + - [ X-Last, { value: "Last", as: equal } ] + - [ X-Not-Here, { as: absent } ] + + # Test 9: SSN-TXN-COUNT condition - multiple transactions in same session +- transactions: + # First transaction + - client-request: + method: "GET" + version: "1.1" + url: /from_4/hello + headers: + fields: + - [ Host, www.example.com ] + - [ Connection, keep-alive ] + - [ Content-Length, "0" ] + - [ uuid, 9 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Server, microserver ] + - [ Content-Length, "0" ] + + proxy-response: + status: 200 + + # Second transaction + - client-request: + method: "GET" + version: "1.1" + url: /from_4/hello + headers: + fields: + - [ Host, www.example.com ] + - [ Connection, keep-alive ] + - [ Content-Length, "0" ] + - [ uuid, 10 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Server, microserver ] + - [ Content-Length, "0" ] + + proxy-response: + status: 200 + + # Third transaction + - client-request: + method: "GET" + version: "1.1" + url: /from_4/hello + headers: + fields: + - [ Host, www.example.com ] + - [ Connection, keep-alive ] + - [ Content-Length, "0" ] + - [ uuid, 11 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Server, microserver ] + - [ Content-Length, "0" ] + + proxy-response: + status: 200 + + # Fourth transaction + - client-request: + method: "GET" + version: "1.1" + url: /from_4/hello + headers: + fields: + - [ Host, www.example.com ] + - [ Connection, keep-alive ] + - [ Content-Length, "0" ] + - [ uuid, 12 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Server, microserver ] + - [ Content-Length, "0" ] + + proxy-response: + status: 200 + headers: + fields: + - [ Connection, { value: "close", as: equal } ] + + # Fifth transaction (with Connection: close) + - client-request: + method: "GET" + version: "1.1" + url: /from_4/world + headers: + fields: + - [ Host, www.example.com ] + - [ Connection, close ] + - [ Content-Length, "0" ] + - [ uuid, 13 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Server, microserver ] + - [ Connection, close ] + - [ Content-Length, "0" ] + + proxy-response: + status: 200 + headers: + fields: + - [ Connection, { value: "close", as: equal } ] + +# Test 10: Cache condition test - multiple requests +# Note: This test involves sleep delays and cache state changes +- transactions: + # First request - cache hit-fresh + - client-request: + # Make sure I/O for writing the cache is complete. + delay: 100ms + + method: "GET" + version: "1.1" + url: /from_5/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 14 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + - [ Cache-Control, "max-age=5,public" ] + content: + size: 6 + data: "CACHED" + + proxy-response: + status: 200 + headers: + fields: + - [ Cache-Result, { value: "hit-fresh", as: equal } ] + + # Note: sleep 8 seconds here - subsequent requests will show stale behavior + # Second request - after cache expires (hit-stale) + - client-request: + method: "GET" + version: "1.1" + url: /from_5/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 15 ] + delay: 8s + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + - [ Cache-Control, "max-age=5,public" ] + content: + size: 6 + data: "CACHED" + + proxy-response: + status: 200 + headers: + fields: + - [ Cache-Result, { value: "hit-stale", as: equal } ] + + # Third request - should hit fresh cache + - client-request: + method: "GET" + version: "1.1" + url: /from_5/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 16 ] + + # The server-response should not be served. + server-response: + status: 500 + + proxy-response: + status: 200 + headers: + fields: + - [ Cache-Result, { value: "hit-fresh", as: equal } ] + +# Test 11: Effective address test +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_6/ + headers: + fields: + - [ Host, www.example.com ] + - [ Real-IP, "1.2.3.4" ] + - [ uuid, 17 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ Effective-IP, { value: "1.2.3.4", as: equal } ] + +# Test 12: Status change test (200 to 303) +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_7/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 18 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 303 + +# Test 13: Implicit hook test - no X-Fie header +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_8/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 19 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-Response-Foo, { value: "No", as: equal } ] + +# Test 14: Implicit hook test - X-Fie: Fie +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_8/ + headers: + fields: + - [ Host, www.example.com ] + - [ X-Fie, "Fie" ] + - [ uuid, 20 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-Response-Foo, { value: "Yes", as: equal } ] + +# Test 15: Implicit hook test - X-Client-Foo: fOoBar +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_8/ + headers: + fields: + - [ Host, www.example.com ] + - [ X-Client-Foo, "fOoBar" ] + - [ uuid, 21 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-Response-Foo, { value: "Prefix", as: equal } ] + +# Test 16: Regex test - no additional headers +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_9/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 22 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-Match-2, { value: yes, as: equal } ] + - [ X-Match, { as: absent } ] + +# Test 17: Regex test - X-Test1: Foobar +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_9/ + headers: + fields: + - [ Host, www.example.com ] + - [ X-Test1, "Foobar" ] + - [ uuid, 23 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-Match, { value: yes, as: equal } ] + - [ X-Match-2, { value: yes, as: equal } ] + +# Test 18: Regex test - X-Test1: none +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_9/ + headers: + fields: + - [ Host, www.example.com ] + - [ X-Test1, "none" ] + - [ uuid, 24 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-Match-2, { value: yes, as: equal } ] + - [ X-Match, { as: absent } ] + +# Test 19: set-body with empty string +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_10/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 25 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + content: + size: 31 + data: "ATS should not serve this body" + + proxy-response: + status: 200 + headers: + fields: + - [ Cache-Control, { value: "no-store", as: equal } ] + - [ Content-Length, { value: "0", as: equal } ] + content: + size: 0 + +# Test 20: set-body with STATUS variable +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_11/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 26 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + content: + size: 31 + data: "ATS should not serve this body" + + proxy-response: + status: 200 + headers: + fields: + - [ Cache-Control, { value: "no-store", as: equal } ] + - [ Content-Length, { value: "3", as: equal } ] + content: + data: "200" + +# Test 21: Nested if/elif/else - X-Foo=foo + X-Bar=bar path +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_12/ + headers: + fields: + - [ Host, www.example.com ] + - [ X-Foo, "foo" ] + - [ X-Bar, "bar" ] + - [ uuid, 27 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-When-200-Before, { value: "Yes", as: equal } ] + - [ X-Foo, { value: "Yes", as: equal } ] + - [ X-Foo-And-Bar, { value: "Yes", as: equal } ] + - [ X-Foo-And-Fie, { as: absent } ] + - [ X-Fie-Anywhere, { as: absent } ] + - [ X-When-200-After, { value: "Yes", as: equal } ] + +# Test 22: Nested if/elif/else - X-Foo=foo + X-Fie=fie path +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_12/ + headers: + fields: + - [ Host, www.example.com ] + - [ X-Foo, "foo" ] + - [ X-Fie, "fie" ] + - [ uuid, 28 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-When-200-Before, { value: "Yes", as: equal } ] + - [ X-Foo, { value: "Yes", as: equal } ] + - [ X-Foo-And-Bar, { as: absent } ] + - [ X-Foo-And-Fie, { value: "Yes", as: equal } ] + - [ X-Fie-Anywhere, { value: "Yes", as: equal } ] + - [ X-When-200-After, { value: "Yes", as: equal } ] + +# Test 23: Nested if/elif/else - X-Foo=maybe path +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_12/ + headers: + fields: + - [ Host, www.example.com ] + - [ X-Foo, "maybe" ] + - [ uuid, 29 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-When-200-Before, { value: "Yes", as: equal } ] + - [ X-Foo, { value: "Maybe", as: equal } ] + - [ X-Foo-And-Bar, { as: absent } ] + - [ X-Foo-And-Fie, { as: absent } ] + - [ X-Fie-Anywhere, { as: absent } ] + - [ X-When-200-After, { value: "Yes", as: equal } ] + +# Test 24: Nested if/elif/else - X-Foo=definitely path +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_12/ + headers: + fields: + - [ Host, www.example.com ] + - [ X-Foo, "definitely" ] + - [ uuid, 30 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-When-200-Before, { value: "Yes", as: equal } ] + - [ X-Foo, { value: "Definitely", as: equal } ] + - [ X-Foo-And-Bar, { as: absent } ] + - [ X-Foo-And-Fie, { as: absent } ] + - [ X-Fie-Anywhere, { as: absent } ] + - [ X-When-200-After, { value: "Yes", as: equal } ] + +# Test 25: Nested if/elif/else - else path (no X-Foo) +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_12/ + headers: + fields: + - [ Host, www.example.com ] + - [ uuid, 31 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-When-200-Before, { value: "Yes", as: equal } ] + - [ X-Foo, { value: "Nothing", as: equal } ] + - [ X-Foo-And-Bar, { as: absent } ] + - [ X-Foo-And-Fie, { as: absent } ] + - [ X-Fie-Anywhere, { as: absent } ] + - [ X-When-200-After, { value: "Yes", as: equal } ] + +# Test 26: Nested if/elif/else - else path with X-Fie +- transactions: + - client-request: + method: "GET" + version: "1.1" + url: /from_12/ + headers: + fields: + - [ Host, www.example.com ] + - [ X-Fie, "fie" ] + - [ uuid, 32 ] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Connection, close ] + + proxy-response: + status: 200 + headers: + fields: + - [ X-When-200-Before, { value: "Yes", as: equal } ] + - [ X-Foo, { value: "Nothing", as: equal } ] + - [ X-Foo-And-Bar, { as: absent } ] + - [ X-Foo-And-Fie, { as: absent } ] + - [ X-Fie-Anywhere, { value: "Yes", as: equal } ] + - [ X-When-200-After, { value: "Yes", as: equal } ] diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.test.py index e7ef3b691c0..658f90a5f86 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.test.py @@ -17,356 +17,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -import ats_autest - Test.Summary = ''' A set of remap rules and tests for header_rewrite. ''' -Test.ContinueOnFail = True - -# Setup ATS and origin, define some convenience variables -mgr = ats_autest.ATSTestManager(Test, When) - -# Common debug logging config -mgr.enable_diagnostics(tags="header_rewrite") -mgr.ts.Disk.records_config.update( - { - 'proxy.config.http.insert_response_via_str': 0, - 'proxy.config.http.auth_server_session_private': 1, - 'proxy.config.http.server_session_sharing.pool': 'global', - 'proxy.config.http.server_session_sharing.match': 'both' - }) - -# mgr.ts.Disk.traffic_out.Content = "gold/header_rewrite-tag.gold" - -############################################################################# -# Setup all the remap rules -# -url_base = "www.example.com/from" -origin_base = f'127.0.0.1:{mgr.origin_port}/to' - -remap_rules = [ - { - "from": "no_path.com/", - "to": "no_path.com?name=brian/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/set_redirect.conf"])] - }, { - "from": f"{url_base}_1/", - "to": f"{origin_base}_1/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/rule_client.conf"])] - }, { - "from": f"{url_base}_2/", - "to": f"{origin_base}_2/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/rule_cond_method.conf"])] - }, { - "from": f"{url_base}_3/", - "to": f"{origin_base}_3/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/rule_l_value.conf"])] - }, { - "from": f"{url_base}_4/", - "to": f"{origin_base}_4/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/rule_set_header_after_ssn_txn_count.conf"])] - }, { - "from": f"{url_base}_5/", - "to": f"{origin_base}_5/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/rule_add_cache_result_header.conf"])] - }, { - "from": f"{url_base}_6/", - "to": f"{origin_base}_6/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/rule_effective_address.conf"])] - }, { - "from": f"{url_base}_7/", - "to": f"{origin_base}_7/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/rule.conf"])] - }, { - "from": f"{url_base}_8/", - "to": f"{origin_base}_8/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/implicit_hook.conf"])] - }, { - "from": f"{url_base}_9/", - "to": f"{origin_base}_9/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/regex_tests.conf"])] - }, { - "from": f"{url_base}_10/", - "to": f"{origin_base}_10/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/rule_empty_body.conf"])] - }, { - "from": f"{url_base}_11/", - "to": f"{origin_base}_11/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/rule_set_body_status.conf"])] - }, { - "from": f"{url_base}_12/", - "to": f"{origin_base}_12/", - "plugins": [("header_rewrite", [f"{mgr.run_dir}/nested_ifs.conf"])] - } -] - -mgr.copy_files('rules/', pattern='*.conf') -mgr.add_remap_rules(remap_rules) - -############################################################################# -# Setup the origin server rquest/response pairs -# -def_resp = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": ""} -origin_rules = [ - ({ - "headers": "GET / HTTP/1.1\r\nHost: no_path.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "", - }, def_resp), - ( - { - "headers": "GET /to_1/hello?=foo=bar HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "", - }, def_resp), - ( - { - "headers": "GET /to_1/hrw-sets.png HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, def_resp), - ({ - "headers": "GET /to_2/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, def_resp), - ({ - "headers": "GET /to_3/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, def_resp), - ( - { - "headers": "GET /to_4/hello HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 0\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, { - "headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\n" - "Content-Length: 0\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }), - ( - { - "headers": "GET /to_4/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" - }, { - "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": "" - }), - ( - { - "headers": "GET /to_5/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, { - "headers": "HTTP/1.1 200 OK\r\nConnection: close\r\nCache-Control: max-age=5,public\r\n\r\n", - "timestamp": "1469733493.993", - "body": "CACHED" - }), - ({ - "headers": "GET /to_6/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, def_resp), - ({ - "headers": "GET /to_7/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, def_resp), - ({ - "headers": "GET /to_8/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, def_resp), - ({ - "headers": "GET /to_9/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, def_resp), - ( - { - "headers": "GET /to_10/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, { - "headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", - "timestamp": "1469733493.993", - "body": "ATS should not serve this body" - }), - ( - { - "headers": "GET /to_11/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, { - "headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", - "timestamp": "1469733493.993", - "body": "ATS should not serve this body" - }), - ({ - "headers": "GET /to_12/ HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - }, def_resp), -] -mgr.add_server_responses(origin_rules) - -# Create all the test cases -curl_proxy = f'--proxy {mgr.localhost} --verbose' -expected_log = "gold/header_rewrite-tag.gold" - -test_runs = [ - { - "desc": "Setup cache hit for tests later (cache hit /miss)", - "curl": f'-s -v -H "{mgr.host_example}" {mgr.localhost}/from_5/', - "gold": "gold/cond_cache_first.gold", - }, - { - "desc": "TO-URL redirect test", - "curl": f'--head http://{mgr.localhost} -H "Host: no_path.com" --verbose', - "gold": "gold/set-redirect.gold", - }, - { - "desc": "CLIENT-URL test", - "curl": f'{curl_proxy} "http://{url_base}_1/hello?=foo=bar"', - "gold": "gold/client-url.gold", - }, - { - "desc": "sets matching", - "curl": f'{curl_proxy} "http://{url_base}_1/hrw-sets.png" -H "X-Testing: foo,bar"', - "gold": "gold/ext-sets.gold", - }, - { - "desc": "elif condition", - "curl": f'{curl_proxy} "http://{url_base}_1/hrw-sets.png" -H "X-Testing: elif"', - "gold": "gold/cond-elif.gold", - }, - { - "desc": "cond method GET", - "curl": f'{curl_proxy} "http://{url_base}_2/"', - "gold": "gold/cond_method.gold", - }, - { - "desc": "cond method DELETE", - "curl": f'--request DELETE {curl_proxy} "http://{url_base}_2/"', - "gold": "gold/cond_method.gold", - }, - { - "desc": "End [L] #5423", - "curl": f'{curl_proxy} "http://{url_base}_3/"', - "gold": "gold/l_value.gold", - }, - { - "desc": "SSN-TXN-COUNT condition", - - # 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. - "multi_curl": - ( - f'{{curl}} -v -H "{mgr.host_example}" -H "{mgr.conn_keepalive}" {mgr.localhost}/from_4/hello &&' - f'{{curl}} -v -H "{mgr.host_example}" -H "{mgr.conn_keepalive}" {mgr.localhost}/from_4/hello &&' - f'{{curl}} -v -H "{mgr.host_example}" -H "{mgr.conn_keepalive}" {mgr.localhost}/from_4/hello &&' - f'{{curl}} -v -H "{mgr.host_example}" -H "{mgr.conn_keepalive}" {mgr.localhost}/from_4/hello &&' - f'{{curl}} -v -H "{mgr.host_example}" -H "Connection: close" {mgr.localhost}/from_4/world'), - "gold": "gold/cond_ssn_txn_count.gold" - }, - { - "desc": "Cache condition test - miss, hit-fresh, hit-stale, hit-fresh", - "multi_curl": - ( - f'{{curl}} -s -v -H "{mgr.host_example}" {mgr.localhost}/from_5/ && ' - f'sleep 8 && {{curl}} -s -v -H "{mgr.host_example}" {mgr.localhost}/from_5/ && ' - f'{{curl}} -s -v -H "{mgr.host_example}" {mgr.localhost}/from_5/'), - "gold": "gold/cond_cache.gold", - }, - { - "desc": "Effective address test", - "curl": f'{curl_proxy} "http://{url_base}_6/" -H "Real-IP: 1.2.3.4"', - "gold": "gold/header_rewrite_effective_address.gold", - }, - { - "desc": "Status change test (200 to 303)", - "curl": f'{curl_proxy} "http://{url_base}_7/"', - "gold": "gold/header_rewrite-303.gold", - }, - { - "desc": "Implicit hook test - no X-Fie header (expect X-Response-Foo: No)", - "curl": f'{curl_proxy} "http://{url_base}_8/"', - "gold": "gold/implicit_hook_no_fie.gold", - }, - { - "desc": "Implicit hook test - X-Fie: Fie (expect X-Response-Foo: Yes)", - "curl": f'{curl_proxy} "http://{url_base}_8/" -H "X-Fie: Fie"', - "gold": "gold/implicit_hook_fie.gold", - }, - { - "desc": "Implicit hook test - X-Client-Foo: fOoBar (expect X-Response-Foo: Prefix)", - "curl": f'{curl_proxy} "http://{url_base}_8/" -H "X-Client-Foo: fOoBar"', - "gold": "gold/implicit_hook_prefix.gold", - }, - { - "desc": "Regex test - no additional headers (expect X-Match-2 only)", - "curl": f'{curl_proxy} "http://{url_base}_9/"', - "gold": "gold/regex_match2_only.gold", - }, - { - "desc": "Regex test - X-Test1: Foobar (expect X-Match and X-Match-2)", - "curl": f'{curl_proxy} "http://{url_base}_9/" -H "X-Test1: Foobar"', - "gold": "gold/regex_both_match.gold", - }, - { - "desc": "Regex test - X-Test1: none (expect X-Match-2 only)", - "curl": f'{curl_proxy} "http://{url_base}_9/" -H "X-Test1: none"', - "gold": "gold/regex_match2_only.gold", - }, - { - "desc": "set-body with empty string (expect empty body with Content-Length: 0)", - "curl": f'{curl_proxy} "http://{url_base}_10/"', - "gold": "gold/set_body_empty.gold", - }, - { - "desc": "set-body with STATUS variable (expect body with '200')", - "curl": f'{curl_proxy} "http://{url_base}_11/"', - "gold": "gold/set_body_status.gold", - "gold_stdout": "gold/set_body_status_stdout.gold", - }, - { - "desc": "Nested if/elif/else - X-Foo=foo + X-Bar=bar path", - "curl": f'{curl_proxy} "http://{url_base}_12/" -H "X-Foo: foo" -H "X-Bar: bar"', - "gold": "gold/nested_ifs_foo_bar.gold", - }, - { - "desc": "Nested if/elif/else - X-Foo=foo + X-Fie=fie path", - "curl": f'{curl_proxy} "http://{url_base}_12/" -H "X-Foo: foo" -H "X-Fie: fie"', - "gold": "gold/nested_ifs_foo_fie.gold", - }, - { - "desc": "Nested if/elif/else - X-Foo=maybe path", - "curl": f'{curl_proxy} "http://{url_base}_12/" -H "X-Foo: maybe"', - "gold": "gold/nested_ifs_maybe.gold", - }, - { - "desc": "Nested if/elif/else - X-Foo=definitely path", - "curl": f'{curl_proxy} "http://{url_base}_12/" -H "X-Foo: definitely"', - "gold": "gold/nested_ifs_definitely.gold", - }, - { - "desc": "Nested if/elif/else - else path (no X-Foo)", - "curl": f'{curl_proxy} "http://{url_base}_12/"', - "gold": "gold/nested_ifs_else.gold", - }, - { - "desc": "Nested if/elif/else - else path with X-Fie (tests second if)", - "curl": f'{curl_proxy} "http://{url_base}_12/" -H "X-Fie: fie"', - "gold": "gold/nested_ifs_else_fie.gold", - }, -] -mgr.execute_tests(test_runs) +Test.ATSReplayTest(replay_file="header_rewrite_bundle.replay.yaml",) From 2ef9863a84d049d35e87b26ddf55b8a423c86d6d Mon Sep 17 00:00:00 2001 From: Brian Neradt Date: Fri, 14 Nov 2025 20:34:14 +0000 Subject: [PATCH 2/2] Review comments. --- tests/gold_tests/autest-site/ats_replay.test.ext | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/gold_tests/autest-site/ats_replay.test.ext b/tests/gold_tests/autest-site/ats_replay.test.ext index 54f809a54f2..10e3b0fe850 100644 --- a/tests/gold_tests/autest-site/ats_replay.test.ext +++ b/tests/gold_tests/autest-site/ats_replay.test.ext @@ -75,13 +75,13 @@ def ATSReplayTest(obj, replay_file: str): '''Create a TestRun that configures ATS and runs HTTP traffic using the replay file. :param obj: The Test object to add the test run to. - :param replay_file: Replay file specifying the test configuraiton and test traffic. + :param replay_file: Replay file specifying the test configuration and test traffic. :returns: The TestRun object. ''' replay_path = replay_file if os.path.isabs(replay_file) else os.path.join(obj.TestDirectory, replay_file) with open(replay_path, 'r') as f: - replay_config = yaml.load(f, Loader=yaml.FullLoader) + replay_config = yaml.safe_load(f) # The user must specify the 'autest' node. if not 'autest' in replay_config: @@ -99,6 +99,7 @@ def ATSReplayTest(obj, replay_file: str): tr.Setup.Copy(dirs_to_copy) # DNS configuration. + dns = None if 'dns' in autest_config: dns_config = autest_config['dns'] name = dns_config['name']