目标
我试图将请求的完整负载作为错误消息的一部分输出,因为我认为请求者给了我一个垃圾负载。原始的工作日志是
setenv TCP_LOG "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq"
log-format "${TCP_LOG} %[var(txn.sendercompid)] %[var(txn.errormessage)] %[var(txn.sendercompid)] %[var(txn.mapped_sendercompid)]"
tcp-request content set-var(txn.errormessage) str("ERROR: SenderCompID not in request") unless { var(txn.sendercompid) -m found }
这正是HAProxy 的标准 tcp 日志格式加上一些我们关心的字符串。
当失败时我想改变的值txn.errormessage
以包含完整的请求负载。
到目前为止我已经尝试过:
tcp-request content set-var(txn.errormessage) str("ERROR: SenderCompID not in request %[req.payload(0,0),regsub(\001,|,g)]")
失败了
> [ALERT] (1) : config : 解析 [/bitnami/haproxy/conf/haproxy.cfg:44] : 获取方法 'str' : 预期 ')' 在 ',0),regsub(\001,|,g)])' 之前
和
tcp-request content set-var(txn.errormessage) req.payload(0,0)
我相信这会记录空字符串
$IP:43384 [11/Jul/2023:20:05:00.748] fix_listener fix_listener/ -1/-1/0 0 PR 1/1/0/0/0 0/0 - - -
虽然我可以看到我被赋予了一个有效载荷
tcp-request content set-var(txn.errormessage) req.len
给我
$IP:43536 [11/Jul/2023:20:25:26.805] fix_listener fix_listener/ -1/-1/0 0 PR 1/1/0/0/0 0/0 - 206 - -
$IP:43540 [11/Jul/2023:20:26:15.825] fix_listener fix_listener/ -1/-1/0 0 PR 1/1/0/0/0 0/0 - 206 - -
$IP:43544 [11/Jul/2023:20:27:04.879] fix_listener fix_listener/ -1/-1/0 0 PR 1/1/0/0/0 0/0 - 206 - -
我能最接近工作的是
tcp-request content set-var(txn.errormessage) req.payload(0,0),hex unless { var(txn.sendercompid) -m found }
它输出十六进制,如果我将其输入到管道中,xxd -r -p
我会得到一堆垃圾,末尾带有一个 IP 地址。
我有阅读大量文档,但tcp-request content set-var
(重定向到后http-request set-var
)仅描述我可以使用作为的表达式
<expr> 是由 sample-fetch 和一些转换器形成的标准 HAProxy 表达式。
并且没有明显的部分描述标准的 HAProxy 表达式。我读了引用和转义部分并且也不明白为什么里面不能有逗号str()
。
问题
- 如何
str("ERROR: SenderCompID not in request %[req.payload(0,0),regsub(\001,|,g)]")
正确引用/格式化才能将字符串与变量连接起来? - 为什么没有设置在我的日志中
txn.errormessage
打印req.payload(0,0)
任何内容? - 在日志语句中打印出请求的完整负载的最简单方法是什么?
答案1
答案
- 见下文
- 我不知道
- 我不知道
经过多次尝试后,我终于得到了我想要的东西:
tcp-request content set-var(txn.errormessage) \
req.payload(0,0),regsub(\x01,|,g),regsub(^,"ERROR: invalid FIX: <"),concat(">") \
unless { req.payload(0,0),fix_is_valid }
在此过程中我学到的一些东西可能会对其他人有所帮助:
,
=|
在 bash 中,但,
也用于分隔参数- 您需要包装硬编码字符串
str()
(除非它们已经是转换器中的参数,在这种情况下您甚至不需要引号) - 单引号转义双引号并开始自己的强引用字符串,我不关心文档怎么说
- 您不能嵌套转换器,并且您不应该尝试。
concat()
比文档让你相信的还要糟糕,并且无法让这一行变得更简单- HAProxy 有
.if / .endif
顶级语句(试图避免尾随unless
),但它们只接受 6 个谓词,而且对我来说没用。 - 文档说非打印字符将自动转换为
#X
其中 X 是字符的 ASCII 十六进制,但这不是我的经验,并且\x01
被打印为非打印字符或空字符串(我正在读取,stdout
所以如果它是实际的 SOH 字符,终端会将其打印为空字符串 - 无论如何,它不会被打印为#01
)