sample fetch methods to feed it into headers or anything. The length should
be limited given that this size will be allocated for each capture during the
whole stream life. Note that the length is only usable with "http-request"
- rules. Please check section 7.3 (Fetching samples), "capture request header"
- and "capture response header" for more information.
+ rules. Such a slot only exists in the section which declares it, so when this
+ rule is placed in a "listen" section which is also used as the backend of
+ another frontend, it is ignored for the streams coming from that frontend.
+ Please check section 7.3 (Fetching samples), "capture request header" and
+ "capture response header" for more information.
If the keyword "id" is used instead of "len", the action tries to store the
captured string in a previously declared capture slot. This is useful to run
--- /dev/null
+varnishtest "capture with a length in a listen section also used as a backend"
+
+# A "capture <expr> len <n>" rule creates a capture slot in the section it
+# is declared in. The capture slots of a stream are those of its frontend,
+# so when the section is a "listen" which is also reached as the backend
+# of another frontend, the slot does not exist for the streams coming from
+# there and the rule must be ignored. Otherwise the rule writes into a slot
+# array which may not exist, or into a slot which belongs to the frontend.
+#
+# The cases are:
+# - the listen section reached directly: the capture works;
+# - reached from a frontend which has no capture at all;
+# - reached from a frontend which has its own capture, which must be
+# left untouched.
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ frontend fe_nocap
+ bind "fd@${fe_nocap}"
+ use_backend lst
+
+ frontend fe_cap
+ bind "fd@${fe_cap}"
+ capture request header x-a len 1
+ use_backend lst
+
+ listen lst
+ bind "fd@${lst}"
+ http-request capture req.hdr(x-b) len 40
+ http-request return status 200 hdr cap0 "%[capture.req.hdr(0)]"
+} -start
+
+client c1 -connect ${h1_lst_sock} {
+ txreq -hdr "x-b: hello"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.cap0 == "hello"
+} -run
+
+client c2 -connect ${h1_fe_nocap_sock} {
+ txreq -hdr "x-b: hello"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.cap0 == "<undef>"
+} -run
+
+client c3 -connect ${h1_fe_cap_sock} {
+ txreq -hdr "x-a: A" -hdr "x-b: hello"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.cap0 == "A"
+} -run
char **cap = s->req_cap;
int len;
+ /* The capture slot was declared in the proxy holding the rule, but the
+ * slots of the stream are those of its frontend. When the rule is
+ * evaluated from a listen section used as a backend, the slot does not
+ * exist, so the rule is ignored.
+ */
+ if (px != strm_fe(s))
+ return ACT_RET_CONT;
+
key = sample_fetch_as_type(s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->arg.cap.expr, SMP_T_STR);
if (!key)
return ACT_RET_CONT;