This is an automated email from the ASF dual-hosted git repository.

bneradt 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 917ca480d9 Gate PP allowlist by header preface (#13125)
917ca480d9 is described below

commit 917ca480d99cb470d0e81bb536191a00ef6cd6e7
Author: Brian Neradt <[email protected]>
AuthorDate: Mon Jun 8 12:50:41 2026 -0500

    Gate PP allowlist by header preface (#13125)
    
    Flexible Proxy Protocol ports currently use
    proxy.config.http.proxy_protocol_allowlist as a source-IP gate for
    every connection, even when traffic never presents a Proxy Protocol
    header. Mixed PP and non-PP deployments can then reject ordinary HTTP
    or TLS clients unexpectedly.
    
    This changes the allowlist check to run only after a v1 or v2 Proxy
    Protocol preface is detected, while still applying the gate before
    parsing or consuming the header. This keeps PP-looking spoof attempts
    behind the trusted-peer check, leaves non-PP bytes untouched for normal
    probing or TLS handshakes, and documents the new behavior with focused
    AuTest coverage.
---
 .../configuration/proxy-protocol.en.rst            | 11 +--
 doc/admin-guide/files/records.yaml.en.rst          | 11 +--
 doc/release-notes/upgrading.en.rst                 |  4 ++
 include/iocore/net/NetVConnection.h                |  2 +
 src/iocore/net/NetVConnection.cc                   | 36 +++++++++-
 src/iocore/net/SSLNetVConnection.cc                | 68 +++++++++---------
 src/proxy/ProtocolProbeSessionAccept.cc            | 42 ++++++-----
 .../proxy_protocol/proxy_protocol.test.py          | 82 ++++++++++++++++++++--
 .../replay/proxy_protocol_allowlist.replay.yaml    | 53 ++++++++++++++
 9 files changed, 243 insertions(+), 66 deletions(-)

diff --git a/doc/admin-guide/configuration/proxy-protocol.en.rst 
b/doc/admin-guide/configuration/proxy-protocol.en.rst
index d7fca8ac51..a2cdfcd6f3 100644
--- a/doc/admin-guide/configuration/proxy-protocol.en.rst
+++ b/doc/admin-guide/configuration/proxy-protocol.en.rst
@@ -49,10 +49,13 @@ configured with 
:ts:cv:`proxy.config.http.proxy_protocol_allowlist`.
 
    .. important::
 
-       If the allowlist is configured, requests will only be accepted from 
these
-       IP addresses for all ports designated for Proxy Protocol in the
-       :ts:cv:`proxy.config.http.server_ports` configuration, regardless of 
whether
-       the connections have the Proxy Protocol header.
+       If the allowlist is configured, connections that begin with a Proxy
+       Protocol header preface will only be accepted from these IP addresses on
+       ports designated for Proxy Protocol in the
+       :ts:cv:`proxy.config.http.server_ports` configuration. Connections
+       without a Proxy Protocol header preface are not restricted by this
+       allowlist; use :file:`ip_allow.yaml` for general source-IP access
+       control.
 
 By default, |TS| uses client's IP address that is from the peer when it 
applies ACL. If you configure a port to
 enable PROXY protocol and want to apply ACL against the IP address delivered 
by PROXY protocol, you need to have ``PROXY`` in
diff --git a/doc/admin-guide/files/records.yaml.en.rst 
b/doc/admin-guide/files/records.yaml.en.rst
index 9ea67b7ccd..6be3348526 100644
--- a/doc/admin-guide/files/records.yaml.en.rst
+++ b/doc/admin-guide/files/records.yaml.en.rst
@@ -2179,10 +2179,13 @@ Proxy User Variables
 
 .. ts:cv:: CONFIG proxy.config.http.proxy_protocol_allowlist STRING ```<ip 
list>```
 
-   This defines a allowlist of server IPs that are trusted to provide
-   connections with Proxy Protocol information.  This is a comma delimited list
-   of IP addresses.  Addressed may be listed individually, in a range separated
-   by a dash or by using CIDR notation.
+   This defines an allowlist of server IPs that are trusted to provide
+   connections with Proxy Protocol information. This allowlist is enforced only
+   for connections that begin with a Proxy Protocol header preface; non-Proxy
+   Protocol traffic on flexible Proxy Protocol ports is not restricted by this
+   setting. Use :file:`ip_allow.yaml` for general source-IP access control. 
This
+   is a comma delimited list of IP addresses. Addresses may be listed
+   individually, in a range separated by a dash, or by using CIDR notation.
 
    ======================= 
===========================================================
    Example                 Effect
diff --git a/doc/release-notes/upgrading.en.rst 
b/doc/release-notes/upgrading.en.rst
index 4fde3d3c7f..c55f4a18df 100644
--- a/doc/release-notes/upgrading.en.rst
+++ b/doc/release-notes/upgrading.en.rst
@@ -163,6 +163,10 @@ The following :file:`records.yaml` changes have been made:
   :ts:cv:`proxy.config.http.header_field_max_size` have been changed to 32KB.
 - The records.yaml entry :ts:cv:`proxy.config.http.server_ports` now also 
accepts the
   ``allow-plain`` option
+- The records.yaml entry :ts:cv:`proxy.config.http.proxy_protocol_allowlist` 
is now enforced
+  only for connections on Proxy Protocol-enabled ports that begin with a Proxy 
Protocol
+  header preface. Non-Proxy Protocol traffic on flexible Proxy Protocol ports 
is no longer
+  restricted by this setting; use :file:`ip_allow.yaml` for general source-IP 
access control.
 - The records.yaml entry 
:ts:cv:`proxy.config.http.cache.max_open_write_retry_timeout` has been added to 
specify a timeout for starting a write to cache
 - The records.yaml entry 
:ts:cv:`proxy.config.net.per_client.max_connections_in` has
   been added to limit the number of connections from a client IP. This works 
the
diff --git a/include/iocore/net/NetVConnection.h 
b/include/iocore/net/NetVConnection.h
index 4da6053539..41b2d80c09 100644
--- a/include/iocore/net/NetVConnection.h
+++ b/include/iocore/net/NetVConnection.h
@@ -505,6 +505,8 @@ public:
   void                 set_proxy_protocol_info(const ProxyProtocol &src);
   const ProxyProtocol &get_proxy_protocol_info() const;
 
+  bool has_proxy_protocol_preface(IOBufferReader *) const;
+  bool has_proxy_protocol_preface(const char *, int64_t) const;
   bool has_proxy_protocol(IOBufferReader *, int max_header_size);
   bool has_proxy_protocol(char *, int64_t *);
 
diff --git a/src/iocore/net/NetVConnection.cc b/src/iocore/net/NetVConnection.cc
index bacfc0e354..4ec91a1342 100644
--- a/src/iocore/net/NetVConnection.cc
+++ b/src/iocore/net/NetVConnection.cc
@@ -45,6 +45,38 @@ DbgCtl dbg_ctl_ssl{"ssl"};
 // NetVConnection
 //
 
+/**
+   PROXY Protocol preface check with IOBufferReader.
+ */
+bool
+NetVConnection::has_proxy_protocol_preface(IOBufferReader *reader) const
+{
+  if (reader == nullptr) {
+    return false;
+  }
+
+  swoc::TextView tv;
+
+  char preface[PPv2_CONNECTION_HEADER_LEN];
+  tv.assign(preface, reader->memcpy(preface, sizeof(preface), 0));
+  return proxy_protocol_detect(tv);
+}
+
+/**
+   PROXY Protocol preface check with a raw buffer.
+ */
+bool
+NetVConnection::has_proxy_protocol_preface(const char *buffer, int64_t 
bytes_r) const
+{
+  if (buffer == nullptr || bytes_r <= 0) {
+    return false;
+  }
+
+  swoc::TextView tv;
+  tv.assign(buffer, static_cast<size_t>(bytes_r));
+  return proxy_protocol_detect(tv);
+}
+
 /**
    PROXY Protocol check with IOBufferReader
 
@@ -55,9 +87,7 @@ NetVConnection::has_proxy_protocol(IOBufferReader *reader, 
int max_header_size)
 {
   swoc::TextView tv;
 
-  char preface[PPv2_CONNECTION_HEADER_LEN];
-  tv.assign(preface, reader->memcpy(preface, sizeof(preface), 0));
-  if (!proxy_protocol_detect(tv)) {
+  if (!this->has_proxy_protocol_preface(reader)) {
     return false;
   }
 
diff --git a/src/iocore/net/SSLNetVConnection.cc 
b/src/iocore/net/SSLNetVConnection.cc
index 4c9d7d35f5..9b1bccd973 100644
--- a/src/iocore/net/SSLNetVConnection.cc
+++ b/src/iocore/net/SSLNetVConnection.cc
@@ -364,45 +364,47 @@ SSLNetVConnection::read_raw_data()
 
     if (this->get_is_proxy_protocol() && this->get_proxy_protocol_version() == 
ProxyProtocolVersion::UNDEFINED) {
       Dbg(dbg_ctl_proxyprotocol, "proxy protocol is enabled on this port");
-      if (pp_ipmap->count() > 0) {
-        Dbg(dbg_ctl_proxyprotocol, "proxy protocol has a configured allowlist 
of trusted IPs - checking");
-
-        // Using get_remote_addr() will return the ip of the
-        // proxy source IP, not the Proxy Protocol client ip.
-        if (!pp_ipmap->contains(swoc::IPAddr(get_remote_addr()))) {
-          Dbg(dbg_ctl_proxyprotocol, "Source IP is NOT in the configured 
allowlist of trusted IPs - closing connection");
-          r = -ENOTCONN; // Need a quick close/exit here to refuse the 
connection!!!!!!!!!
-          goto proxy_protocol_bypass;
+      if (this->has_proxy_protocol_preface(buffer, r)) {
+        if (pp_ipmap->count() > 0) {
+          Dbg(dbg_ctl_proxyprotocol, "proxy protocol has a configured 
allowlist of trusted IPs - checking");
+
+          // Using get_remote_addr() will return the ip of the
+          // proxy source IP, not the Proxy Protocol client ip.
+          if (!pp_ipmap->contains(swoc::IPAddr(get_remote_addr()))) {
+            Dbg(dbg_ctl_proxyprotocol, "Source IP is NOT in the configured 
allowlist of trusted IPs - closing connection");
+            r = -ENOTCONN; // Need a quick close/exit here to refuse the 
connection!!!!!!!!!
+            goto proxy_protocol_bypass;
+          } else {
+            char new_host[INET6_ADDRSTRLEN];
+            Dbg(dbg_ctl_proxyprotocol, "Source IP [%s] is in the trusted 
allowlist for proxy protocol",
+                ats_ip_ntop(this->get_remote_addr(), new_host, 
sizeof(new_host)));
+          }
         } else {
-          char new_host[INET6_ADDRSTRLEN];
-          Dbg(dbg_ctl_proxyprotocol, "Source IP [%s] is in the trusted 
allowlist for proxy protocol",
-              ats_ip_ntop(this->get_remote_addr(), new_host, 
sizeof(new_host)));
+          Dbg(dbg_ctl_proxyprotocol, "proxy protocol DOES NOT have a 
configured allowlist of trusted IPs but "
+                                     "proxy protocol is enabled on this port - 
processing all connections with Proxy Protocol "
+                                     "headers");
         }
-      } else {
-        Dbg(dbg_ctl_proxyprotocol, "proxy protocol DOES NOT have a configured 
allowlist of trusted IPs but "
-                                   "proxy protocol is enabled on this port - 
processing all connections");
-      }
 
-      auto const stored_r = r;
-      if (this->has_proxy_protocol(buffer, &r)) {
-        Dbg(dbg_ctl_proxyprotocol, "ssl has proxy protocol header");
-        if (dbg_ctl_proxyprotocol.on()) {
-          IpEndpoint src;
-          src.sa = *(this->get_proxy_protocol_src_addr());
-          IpEndpoint dst;
-          dst.sa = *(this->get_proxy_protocol_dst_addr());
-          ip_port_text_buffer src_ipb, dst_ipb;
-          ats_ip_nptop(&src, src_ipb, sizeof(src_ipb));
-          ats_ip_nptop(&dst, dst_ipb, sizeof(dst_ipb));
-          DbgPrint(dbg_ctl_proxyprotocol, "ssl proxy protocol v%d header 
parsed: src=[%s] dst=[%s]",
-                   static_cast<int>(this->get_proxy_protocol_version()), 
src_ipb, dst_ipb);
+        auto const stored_r = r;
+        if (this->has_proxy_protocol(buffer, &r)) {
+          Dbg(dbg_ctl_proxyprotocol, "ssl has proxy protocol header");
+          if (dbg_ctl_proxyprotocol.on()) {
+            IpEndpoint src;
+            src.sa = *(this->get_proxy_protocol_src_addr());
+            IpEndpoint dst;
+            dst.sa = *(this->get_proxy_protocol_dst_addr());
+            ip_port_text_buffer src_ipb, dst_ipb;
+            ats_ip_nptop(&src, src_ipb, sizeof(src_ipb));
+            ats_ip_nptop(&dst, dst_ipb, sizeof(dst_ipb));
+            DbgPrint(dbg_ctl_proxyprotocol, "ssl proxy protocol v%d header 
parsed: src=[%s] dst=[%s]",
+                     static_cast<int>(this->get_proxy_protocol_version()), 
src_ipb, dst_ipb);
+          }
+        } else {
+          Dbg(dbg_ctl_proxyprotocol, "proxy protocol preface was present, but 
Proxy Protocol header could not be parsed");
+          r = stored_r;
         }
       } else {
         Dbg(dbg_ctl_proxyprotocol, "proxy protocol was enabled, but Proxy 
Protocol header was not present");
-        // We are flexible with the Proxy Protocol designation. Maybe not all
-        // connections include Proxy Protocol. Revert to the stored value of r 
so
-        // we can process the bytes that are on the wire (likely a 
CLIENT_HELLO).
-        r = stored_r;
       }
     }
   } // end of Proxy Protocol processing
diff --git a/src/proxy/ProtocolProbeSessionAccept.cc 
b/src/proxy/ProtocolProbeSessionAccept.cc
index e88926456d..b8b3b2c8db 100644
--- a/src/proxy/ProtocolProbeSessionAccept.cc
+++ b/src/proxy/ProtocolProbeSessionAccept.cc
@@ -111,27 +111,33 @@ struct ProtocolProbeTrampoline : public Continuation, 
public ProtocolProbeSessio
 
     if (netvc->get_is_proxy_protocol() && netvc->get_proxy_protocol_version() 
== ProxyProtocolVersion::UNDEFINED) {
       Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: proxy protocol is enabled 
on this port");
-      if (pp_ipmap->count() > 0) {
-        Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: proxy protocol has a 
configured allowlist of trusted IPs - checking");
-        if (!pp_ipmap->contains(swoc::IPAddr(netvc->get_remote_addr()))) {
+      if (netvc->has_proxy_protocol_preface(reader)) {
+        if (pp_ipmap->count() > 0) {
+          Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: proxy protocol has a 
configured allowlist of trusted IPs - checking");
+          if (!pp_ipmap->contains(swoc::IPAddr(netvc->get_remote_addr()))) {
+            Dbg(dbg_ctl_proxyprotocol,
+                "ioCompletionEvent: Source IP is NOT in the configured 
allowlist of trusted IPs - closing connection");
+            goto done;
+          } else {
+            char new_host[INET6_ADDRSTRLEN];
+            Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: Source IP [%s] is 
trusted in the allowlist for proxy protocol",
+                ats_ip_ntop(netvc->get_remote_addr(), new_host, 
sizeof(new_host)));
+          }
+        } else {
           Dbg(dbg_ctl_proxyprotocol,
-              "ioCompletionEvent: Source IP is NOT in the configured allowlist 
of trusted IPs - closing connection");
-          goto done;
+              "ioCompletionEvent: proxy protocol DOES NOT have a configured 
allowlist of trusted IPs but proxy protocol is "
+              "enabled on this port - processing all connections with Proxy 
Protocol headers");
+        }
+
+        HttpConfigParams *param           = HttpConfig::acquire();
+        int               max_header_size = param->pp_hdr_max_size;
+        HttpConfig::release(param);
+        if (netvc->has_proxy_protocol(reader, max_header_size)) {
+          Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: http has proxy 
protocol header");
         } else {
-          char new_host[INET6_ADDRSTRLEN];
-          Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: Source IP [%s] is 
trusted in the allowlist for proxy protocol",
-              ats_ip_ntop(netvc->get_remote_addr(), new_host, 
sizeof(new_host)));
+          Dbg(dbg_ctl_proxyprotocol,
+              "ioCompletionEvent: proxy protocol preface was present, but 
Proxy Protocol header could not be parsed");
         }
-      } else {
-        Dbg(dbg_ctl_proxyprotocol,
-            "ioCompletionEvent: proxy protocol DOES NOT have a configured 
allowlist of trusted IPs but proxy protocol is "
-            "enabled on this port - processing all connections");
-      }
-      HttpConfigParams *param           = HttpConfig::acquire();
-      int               max_header_size = param->pp_hdr_max_size;
-      HttpConfig::release(param);
-      if (netvc->has_proxy_protocol(reader, max_header_size)) {
-        Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: http has proxy protocol 
header");
       } else {
         Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: proxy protocol was 
enabled, but Proxy Protocol header was not present");
       }
diff --git a/tests/gold_tests/proxy_protocol/proxy_protocol.test.py 
b/tests/gold_tests/proxy_protocol/proxy_protocol.test.py
index e2abc9f713..47f39729fe 100644
--- a/tests/gold_tests/proxy_protocol/proxy_protocol.test.py
+++ b/tests/gold_tests/proxy_protocol/proxy_protocol.test.py
@@ -60,8 +60,8 @@ ssl_multicert:
                 "proxy.config.http.insert_forwarded": "for|by=ip|proto",
                 "proxy.config.http.insert_client_ip": 2,
                 "proxy.config.http.insert_squid_x_forwarded_for": 1,
-                "proxy.config.ssl.server.cert.path": 
f"{self.ts.Variables.SSLDir}",
-                "proxy.config.ssl.server.private_key.path": 
f"{self.ts.Variables.SSLDir}",
+                "proxy.config.ssl.server.cert.path": self.ts.Variables.SSLDir,
+                "proxy.config.ssl.server.private_key.path": 
self.ts.Variables.SSLDir,
                 "proxy.config.diags.debug.enabled": 1,
                 "proxy.config.diags.debug.tags": "proxyprotocol",
             })
@@ -108,6 +108,79 @@ logging:
         self.checkAccessLog()
 
 
+class ProxyProtocolAllowlistTest:
+    """Test that the PROXY Protocol allowlist applies only to PP-prefaced 
traffic."""
+
+    replay_file = "replay/proxy_protocol_allowlist.replay.yaml"
+
+    def __init__(self):
+        self.setupOriginServer()
+        self.setupTS()
+
+    def setupOriginServer(self):
+        self.server = Test.MakeVerifierServerProcess("pp-allowlist-server", 
self.replay_file)
+
+    def setupTS(self):
+        self.ts = Test.MakeATSProcess("ts_pp_allowlist", enable_tls=True, 
enable_cache=False, enable_proxy_protocol=True)
+
+        self.ts.addDefaultSSLFiles()
+        self.ts.Disk.ssl_multicert_yaml.AddLines(
+            """
+ssl_multicert:
+  - dest_ip: "*"
+    ssl_cert_name: server.pem
+    ssl_key_name: server.key
+""".split("\n"))
+
+        self.ts.Disk.remap_config.AddLine(f"map / 
http://127.0.0.1:{self.server.Variables.http_port}/";)
+
+        self.ts.Disk.records_config.update(
+            {
+                "proxy.config.http.proxy_protocol_allowlist": "192.0.2.1",
+                "proxy.config.ssl.server.cert.path": self.ts.Variables.SSLDir,
+                "proxy.config.ssl.server.private_key.path": 
self.ts.Variables.SSLDir,
+                "proxy.config.diags.debug.enabled": 1,
+                "proxy.config.diags.debug.tags": "proxyprotocol",
+            })
+
+    def addCurlRun(self, name, args, return_code=0, expect_status=None, 
start_processes=False):
+        tr = Test.AddTestRun(name)
+        tr.TimeOut = 10
+        tr.MakeCurlCommand(args, ts=self.ts)
+        tr.Processes.Default.ReturnCode = return_code
+
+        if expect_status is not None:
+            tr.Processes.Default.Streams.stdout = 
Testers.ContainsExpression(expect_status, f"Expected HTTP {expect_status}")
+
+        if start_processes:
+            tr.Processes.Default.StartBefore(self.server)
+            tr.Processes.Default.StartBefore(self.ts)
+
+        tr.StillRunningAfter = self.server
+        tr.StillRunningAfter = self.ts
+
+    def run(self):
+        self.addCurlRun(
+            "Non-PP HTTP traffic bypasses proxy_protocol_allowlist",
+            f'-sS -o /dev/null -w "%{{http_code}}" -H "uuid: 1" 
http://127.0.0.1:{self.ts.Variables.proxy_protocol_port}/get',
+            expect_status="200",
+            start_processes=True)
+        self.addCurlRun(
+            "Non-PP TLS traffic bypasses proxy_protocol_allowlist", f'-k -sS 
-o /dev/null -w "%{{http_code}}" -H "uuid: 2" '
+            
f'https://127.0.0.1:{self.ts.Variables.proxy_protocol_ssl_port}/get',
+            expect_status="200")
+        self.addCurlRun(
+            "PP-prefaced HTTP traffic is rejected when peer is not 
allowlisted",
+            f'-sS -o /dev/null --max-time 5 --haproxy-protocol '
+            f'http://127.0.0.1:{self.ts.Variables.proxy_protocol_port}/get',
+            return_code=Any(52, 56))
+        self.addCurlRun(
+            "PP-prefaced TLS traffic is rejected when peer is not allowlisted",
+            f'-k -sS -o /dev/null --max-time 5 --haproxy-protocol '
+            
f'https://127.0.0.1:{self.ts.Variables.proxy_protocol_ssl_port}/get',
+            return_code=Any(35, 52, 56))
+
+
 class ProxyProtocolOutTest:
     """Test that ATS can send Proxy Protocol."""
 
@@ -166,8 +239,8 @@ ssl_multicert:
 
         self._ts.Disk.records_config.update(
             {
-                "proxy.config.ssl.server.cert.path": 
f"{self._ts.Variables.SSLDir}",
-                "proxy.config.ssl.server.private_key.path": 
f"{self._ts.Variables.SSLDir}",
+                "proxy.config.ssl.server.cert.path": self._ts.Variables.SSLDir,
+                "proxy.config.ssl.server.private_key.path": 
self._ts.Variables.SSLDir,
                 "proxy.config.diags.debug.enabled": 1,
                 "proxy.config.diags.debug.tags": "http|proxyprotocol",
                 "proxy.config.http.proxy_protocol_out": self._pp_version,
@@ -240,6 +313,7 @@ ssl_multicert:
 
 ProxyProtocolInTest("nocp", False).run()
 ProxyProtocolInTest("cp", True).run()
+ProxyProtocolAllowlistTest().run()
 
 # non-tunnling HTTP to origin
 ProxyProtocolOutTest(pp_version=-1, is_tunnel=False, 
is_tls_to_origin=False).run()
diff --git 
a/tests/gold_tests/proxy_protocol/replay/proxy_protocol_allowlist.replay.yaml 
b/tests/gold_tests/proxy_protocol/replay/proxy_protocol_allowlist.replay.yaml
new file mode 100644
index 0000000000..6614fa06c5
--- /dev/null
+++ 
b/tests/gold_tests/proxy_protocol/replay/proxy_protocol_allowlist.replay.yaml
@@ -0,0 +1,53 @@
+#  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"
+
+sessions:
+  - protocol:
+      stack: http
+    transactions:
+      - client-request:
+          method: GET
+          version: "1.1"
+          url: /get
+          headers:
+            fields:
+              - [uuid, 1]
+
+        server-response:
+          status: 200
+
+        proxy-response:
+          status: 200
+
+  - protocol:
+      stack: https
+    transactions:
+      - client-request:
+          method: GET
+          version: "1.1"
+          url: /get
+          headers:
+            fields:
+              - [uuid, 2]
+
+        server-response:
+          status: 200
+
+        proxy-response:
+          status: 200

Reply via email to