]> git.kaiwu.me - haproxy.git/commitdiff
REGTESTS: log: check the escaping performed by the +json option
authorWilly Tarreau <w@1wt.eu>
Thu, 3 Sep 2026 05:05:35 +0000 (07:05 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 3 Sep 2026 06:32:25 +0000 (08:32 +0200)
Check that a control character, a byte above the printable range and the
two characters which JSON requires to be escaped all come out escaped, and
that nothing outside 32..126 reaches the ring. The test fails without the
previous commit.

reg-tests/log/log_json.vtc [new file with mode: 0644]

diff --git a/reg-tests/log/log_json.vtc b/reg-tests/log/log_json.vtc
new file mode 100644 (file)
index 0000000..f2fe4dc
--- /dev/null
@@ -0,0 +1,77 @@
+varnishtest "Check the escaping performed by the +json option"
+feature ignore_unknown_macro
+
+# Section 8.6 of the config manual states that only the characters from 32 to
+# 126 are emitted as-is in the logs, everything else being encoded, and the
+# JSON encoding has no reason to be more permissive than the plain one.
+# Escaping them all also makes the output valid UTF-8, which RFC 8259 #8.1
+# requires, without having to guess what the logged bytes represent: a header
+# value is arbitrary bytes, not text.
+
+haproxy h1 -conf {
+    global
+    .if feature(THREAD)
+        thread-groups 1
+    .endif
+
+    ring myring
+        size 16384
+        format raw
+
+    defaults
+        mode http
+        timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+        timeout client  "${HAPROXY_TEST_TIMEOUT-5s}"
+        timeout server  "${HAPROXY_TEST_TIMEOUT-5s}"
+
+    frontend fe
+        bind "fd@${fe}"
+        capture request header x len 64
+        log ring@myring local0
+        log-format "{\"hdr\":%{+json}[capture.req.hdr(0)],\"bin\":%{+json}[str(Gw==),b64dec]}"
+        http-request return status 200
+} -start
+
+# an ESC, which has no two-character form, a tab, which has one, a double quote
+# and a backslash
+client c1 -connect ${h1_fe_sock} {
+    txreq -url "/ctl" -hdr "x: A\x1b[31m\tB\"C\\D"
+    rxresp
+    expect resp.status == 200
+} -run
+
+# bytes above the printable range, here a valid UTF-8 sequence and a lone
+# continuation byte, are encoded the same way: one escape per byte
+client c2 -connect ${h1_fe_sock} {
+    txreq -url "/high" -hdr "x: A\xc3\xa9B\xaaC"
+    rxresp
+    expect resp.status == 200
+} -run
+
+delay 0.2
+
+# the ESC comes out as the six-character form and the tab as the short one, in
+# both the string sample and the binary sample paths
+haproxy h1 -cli {
+    send "show events myring"
+    expect ~ "A\\\\u001B\\[31m\\\\tB"
+}
+
+haproxy h1 -cli {
+    send "show events myring"
+    expect ~ "\"bin\":\"\\\\u001B\""
+}
+
+# one escape per byte above the printable range, so the output stays plain
+# ASCII and no byte can be mistaken for a sequence introducer
+haproxy h1 -cli {
+    send "show events myring"
+    expect ~ "A\\\\u00C3\\\\u00A9B\\\\u00AAC"
+}
+
+# nothing outside 32..126 reached the ring, which "-s" would have turned into
+# a '?'
+haproxy h1 -cli {
+    send "show events myring -s"
+    expect !~ "\\?"
+}