From: Christopher Faulet Date: Fri, 2 Oct 2026 19:21:42 +0000 (+0200) Subject: REGTESTS: filters: Exercise TCP Lua payload chains and sequencing X-Git-Tag: v3.5-dev9~58 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=64a7d693d93356b79d49f1499634772628211572;p=haproxy.git REGTESTS: filters: Exercise TCP Lua payload chains and sequencing Use same-length, non-commuting Lua substitutions to observe the actual TCP request and response evaluation order without depending on packet boundaries. Mix the rewrites with trace and active bandwidth filters. Inherit independent channel sequences from named defaults, reverse them locally by first detaching the inherited child to the class anchor, and check class-wide disabling followed by id-specific enabling. Include a fully disabled Lua chain and a legacy chain retaining symmetric order. Use HTTP framing only to check complete bodies over TCP; the proxies do not parse HTTP and the Lua filters are not HTX-capable. --- diff --git a/reg-tests/filters/lua-tcp-rewrite.lua b/reg-tests/filters/lua-tcp-rewrite.lua new file mode 100644 index 000000000..409398240 --- /dev/null +++ b/reg-tests/filters/lua-tcp-rewrite.lua @@ -0,0 +1,33 @@ +-- Same-length, non-commuting substitutions make channel order observable on +-- the wire. No packet boundaries or transport timing enter the assertions. +local function register(name, from, to) + local F = { id = name, flags = 0, from = from, to = to } + + function F:new() + return setmetatable({}, { __index = self }) + end + + function F:start_analyze(txn, chn) + filter.register_data_filter(self, chn) + return filter.CONTINUE + end + + function F:tcp_payload(txn, chn) + local count = chn:input() + if count == 0 then + return 0 + end + local data = chn:data(0, count) + local replaced = data:gsub(self.from, self.to) + assert(chn:set(replaced, 0, count) == count) + return count + end + + core.register_filter(name, F, function(conf, args) + return conf + end) +end + +register("rewrite-a", "a", "b") +register("rewrite-b", "b", "c") +register("rewrite-c", "c", "a") diff --git a/reg-tests/filters/lua-tcp.vtc b/reg-tests/filters/lua-tcp.vtc new file mode 100644 index 000000000..3f09bc67d --- /dev/null +++ b/reg-tests/filters/lua-tcp.vtc @@ -0,0 +1,127 @@ +varnishtest "TCP Lua payload chains honor inherited per-side sequences and state" + +feature cmd "$HAPROXY_PROGRAM -cc 'feature(LUA)'" +feature ignore_unknown_macro + +# HTTP framing is only a convenient way to check complete bodies over TCP. +# The proxies do not parse HTTP and the Lua filters have no HTX flag. +server s1 { + rxreq + expect req.body == "cccccc" + txresp -body "aabbcc" +} -start + +server s2 { + rxreq + expect req.body == "bbbbcc" + txresp -body "aabbcc" +} -start + +server s3 { + rxreq + expect req.body == "aaaabb" + txresp -body "aabbcc" +} -start + +server s4 { + rxreq + expect req.body == "bbbbcc" + txresp -body "aabbcc" +} -start + +haproxy h1 -conf { + global + nbthread 1 + tune.lua.bool-sample-conversion normal + lua-load "${testdir}/lua-tcp-rewrite.lua" + defaults plain + mode tcp + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend ordered from plain + bind "fd@${ordered}" + default_backend ordered_be + frontend reversed from plain + bind "fd@${reversed}" + default_backend reversed_be + frontend off from plain + bind "fd@${off}" + default_backend off_be + frontend legacy from plain + bind "fd@${legacy}" + default_backend legacy_be + + defaults rewrites from plain + filter-config trace id trace enabled quiet + filter-config lua id rewrite-a enabled + filter-config lua id rewrite-b enabled + filter-config lua id rewrite-c enabled + filter-disable lua/rewrite-c + filter-config bwlim-in id upload enabled default-limit 1m default-period 1s + filter-config bwlim-out id download enabled default-limit 1m default-period 1s + filter-sequence global lua/rewrite-b:before(lua/rewrite-a) + filter-sequence request lua/rewrite-a:before(lua/rewrite-b) + filter-sequence response lua/rewrite-b:before(lua/rewrite-a) + + backend ordered_be from rewrites + tcp-request content set-bandwidth-limit upload + tcp-response content set-bandwidth-limit download + server s1 ${s1_addr}:${s1_port} + + backend reversed_be from rewrites + filter-disable lua + filter-enable lua/rewrite-a lua/rewrite-b + # Detach the inherited child to the class anchor before reversing + # the relation. Moving its parent under it directly creates a cycle. + filter-sequence request lua/rewrite-a:before(lua) lua/rewrite-b:before(lua/rewrite-a) + filter-sequence response lua/rewrite-b:before(lua) lua/rewrite-a:before(lua/rewrite-b) + tcp-request content set-bandwidth-limit upload + tcp-response content set-bandwidth-limit download + server s2 ${s2_addr}:${s2_port} + + backend off_be from rewrites + filter-disable lua + tcp-request content set-bandwidth-limit upload + tcp-response content set-bandwidth-limit download + server s3 ${s3_addr}:${s3_port} + + backend legacy_be from plain + filter trace quiet + filter lua.rewrite-b + filter lua.rewrite-a + filter bwlim-in upload default-limit 1m default-period 1s + filter bwlim-out download default-limit 1m default-period 1s + tcp-request content set-bandwidth-limit upload + tcp-response content set-bandwidth-limit download + server s4 ${s4_addr}:${s4_port} +} -start + +client c1 -connect ${h1_ordered_sock} { + txreq -req POST -body "aaaabb" + rxresp + expect resp.status == 200 + expect resp.body == "bbcccc" +} -run + +client c2 -connect ${h1_reversed_sock} { + txreq -req POST -body "aaaabb" + rxresp + expect resp.status == 200 + expect resp.body == "cccccc" +} -run + +client c3 -connect ${h1_off_sock} { + txreq -req POST -body "aaaabb" + rxresp + expect resp.status == 200 + expect resp.body == "aabbcc" +} -run + +client c4 -connect ${h1_legacy_sock} { + txreq -req POST -body "aaaabb" + rxresp + expect resp.status == 200 + expect resp.body == "bbcccc" +} -run